Wo stehe ich gerade? Die Steuerung des Raumschiffs ist fertig und ich habe am Wochenende den ersten Missile als "Schuss" fertig gestellt. Jetzt kommt Schuss 2 - also wie bei Phobos soll das Raumschiff abwechselnd links und rechts schiessen können. Das werde ich nächste Woche implementieren und dann den Code hier hochladen. Das ist gar nicht so unkompliziert zu programmieren und ich habe beschlossen, daß ich auf die erweiterten Möglichkeiten vom MADS Crossassembler zurückgreife und if - Bedingungen in den Code mit einbeziehe. Das macht den Code lesbarer und auch einfacher für mich zu programmieren... Die Compabilität zu den alten Assemblern nimmt natürlich ab... ich hoffe ihr könnt auch zukünftig den Code nachvollziehen! Wer aktuell in Assembler programmieren will sollte tatsächlich auf die Umgebung Eclipse mit WUDSN und MADS-Assembler zurückgreifen! LG Peter
Return to Phobos
Sooooo .... ich habe heute die Schüsse des Raumschiffes drin! Dabei habe ich mir ganz schön die Programmierfinger verbogen, denn zwei Missiles so zu programmieren, das sie abwechselnd aus dem rechten bzw. linken "Schussrohr" des Raumschiffes loslaufen und je nach Schusslänge auch durchaus gleichzeitig zu sehen sind ... also zur richtigen Zeit jeweils sperren und freigeben etc. war ganz schön tricky... aber es läuft jetzt. Der Code dafür sieht recht umständlich aus und ich habe mehrere Hilfsvariablen benutzen müssen - es läuft auch noch nicht komplett fehlerfrei - je nach Höhe des Raumschiffes mehr oder weniger gut! Hier muss ich noch ein wenig den Code verfeinern...
Hier der Code für den Header:
var1 = $a0
var2 = $a2
var3 = $a4
var4 = $a6
var5 = $a8
var6 = $b2
var7 = $b4
lms1 = $b6
lms2 = $b8
lmslo = $a0
lmshi = $a2
delay = $b0
play1 = $92
play2 = $94
play3 = $96
play4 = $98
miss1 = $c0
miss2 = $c2
miss3 = $c4
miss4 = $c6
rechts = $c8
links = $c9
xposp1 = $ca
yposp1 = $cb
joyst1 = $cc
kollp0 = $cd
xposm1 = $ce
yposm1 = $cf
xposm2 = $d0
yposm2 = $d1
kollm1 = $d2
kollm2 = $d3
feuer1 = $d4
feuer2 = $d5
yposm1hilf = $d6
feuer3 = $d7
feuer4 = $d8
yposm2hilf = $d9
feuer5 = $da
Und hier der Programmcode:
org $2000
icl '../hardware.txt'
icl '../header.txt'
icl 'character.asm'
icl 'lands.asm'
dlist .byte 112,112,112,100
.byte 30,75
.byte 36,36,36,36,36,36,36,36,36,36,36,36
.byte 36,36,36,36,36,36,36,36,36,4,112
.byte 65,32,156
pm1 .byte 0,24,60,36,36,126,126,255,219,219,129,129,129,0
mi1 .byte 15,15,15,15
mi2 .byte 12,12,12,12
mi3 .byte 12,12,12,12
mi4 .byte 12,12,12,12
.proc main
main1 jsr displaylist ;Subroutine Displaylist-Aufbau
mva #33 yposp1
mva #120 xposp1
mva #42 yposm1
mva #0 xposm1
mva #94 yposm2
mva #100 xposm2
Start1 mva #>chr chbas ;HighByte Character Pointer auf $2000 setzen
mva #192 gprior ;GTIA Modus 3 (16 Farben) initialisieren
mva #0 color4 ;Hintergrundfarbe / Helligkeit festlegen
lda #0 \ tax \ sta var3 \ sta var4 \ sta var6 \ sta var7 \ sta var6+1
mva <lands var6
mva >lands var6+1
mva #0 kollp0
; Player vorbereiten und initialisieren
lda ramtop
sec
sbc #16
sta pmbase
clc
adc #3
sta miss1+1
adc #1
sta play1+1
mva #62 sdmctl
mva #220 pcolr0
mva #220 pcolr1
mva #122 pcolr2
mva #122 pcolr3
mva #1 gprior
mva #3 gractl
mva #1 sizep0
mva #1 sizep1
mva #0 sizem
mva #0 rechts
mva #2 hitclr
main2
ldy #255 ;Speicher Player 1 leeren
lda #0
sta play1
@ sta (play1),y
dey
bpl @-
clc
ldy yposp1 ;verticale Startpos. Player 1 + füllen
ldx #0
@ lda pm1,x
sta (play1),y
iny
inx
cpx #14
bne @-
clc
ldy #0
ldx #0
@ lda mi1,x
sta (miss1),y
iny
inx
cpx #2
bne @-
lda xposm1
sta p0pf
lda xposm2
sta p1pf
ldx #>vbinter ;VB-Interrupt VektorHi
ldy #<vbinter ;VB-Interrupt VektorLo
lda #7 ;Deferred Mode mit lda #7 festlegen
jsr setvbv ;Vektor für die eigene Routine über setvbv eintragen
hauptprogramm
clc
lda kollp0
cmp #1
bcc @+
jsr kollision
jmp start1
@
jsr letztereihe ;letzte Reihe (lands) Bildschirm1 printen (sichtbar)
jsr feinscroll ;Feinscroll Bildschirm1 ausführen (sichtbar)
mva #$30 var1 ;var1 auf 30000 ($7530) setzen
mva #$75 var1+1
mva #$f0 var2 ;var2 auf 30960 ($78f0) setzen
mva #$78 var2+1
jsr grobscroll ;Bildschirm1 kopieren + grobscroll
mva #$18 var1 ;var1 + var2 auf 31000 ($7918) setzen
mva #$18 var2
mva #$79 var1+1
mva #$79 var2+1
mva #1 delay
jsr wartes
jsr umschalten ;umschalten auf Bildschirm2 - Bildschirm2 wird sichtbar
jsr letztereihe
jsr feinscroll ;Feinscroll Bildschirm2 ausführen (sichtbar)
mva #$08 var2 ;var1 auf 29960 ($7508) setzen
mva #$75 var2+1
mva #$18 var1 ;var2 auf 31000 ($7918) setzen
mva #$79 var1+1
jsr grobscroll ;;Bildschirm2 kopieren + grobscroll
mva #$30 var1 ;var1 + var2 auf 30000 ($7530) setzen
mva #$30 var2
mva #$75 var1+1
mva #$75 var2+1
mva #1 delay
jsr wartes
jsr umschalten ;umschalten auf Bildschirm1 - Bildschirm1 wird sichtbar
;Ende der Bildschirmausführung / Kontrolle Durchläufe
sec
lda #38 ; - 36 = Anzahl der Durchläufe
sbc var6+1
bpl @+
jmp start1 ;Stop hier
@ jmp hauptprogramm ;weiter
.endp
; _____________________________________________________________________________________
;
; ---------------------------- S U B R O U T I N E N ----------------------------------
; _____________________________________________________________________________________
;vertical blank interrupt für Joystick / PM
vbinter
pha
txa
pha
clc ;Kollision Player 0 Abfragen
lda p0pf
cmp #1
bcc @+
mva #1 kollp0
@ mva #2 hitclr
clc ;Joystickabfragen Player1
lda stick0
cmp #15 ;keine Joystickaktion
bcs @+
cmp #14
bcs nachob
cmp #13
bcs nachun
cmp #11
bcs nachli
cmp #10
bcs nachliob
cmp #9
bcs nachliun
sec
cmp #7
bcs nachre
cmp #6
bcs nachreob
cmp #5
bcs nachreun
@ jmp write
nachre clc
lda xposp1
cmp #192
bcs @+
inc xposp1
@ jmp write
nachreun
clc
lda xposp1
cmp #192
bcs @+
inc xposp1
@ jmp nachun
nachreob
clc
lda xposp1
cmp #192
bcs @+
inc xposp1
@ jmp nachob
nachli sec
lda xposp1
cmp #49
bcc @+
dec xposp1
@ jmp write
nachliun
sec
lda xposp1
cmp #49
bcc @+
dec xposp1
@ jmp nachun
nachliob
sec
lda xposp1
cmp #49
bcc @+
dec xposp1
@ jmp nachob
nachob
dec yposp1
clc
ldy yposp1 ;verticale Startpos. Player 1 + füllen
ldx #0
@ lda pm1,x
sta (play1),y
iny
inx
cpx #14
bne @-
jmp write
nachun
inc yposp1
clc
ldy yposp1 ;verticale Startpos. Player 1 + füllen
ldx #0
@ lda pm1,x
sta (play1),y
iny
inx
cpx #14
bne @-
jmp write
@ clc
write
lda xposp1
sta hposp0
;---------- Abfrage Feuerknopf und Routine Schuss links-------
#if .byte strig0<#1 .and .byte feuer3=#0
#if .byte feuer5=#0 .or .byte feuer5>#180
mva #1 feuer1
mva #1 feuer3
mva xposp1 p0pf
lda yposp1
adc #9
sta feuer2
#end
#end
#if .byte feuer1=#1
ldy feuer2
lda #0
sta (miss1),y
iny
sty feuer2
iny
lda #3
sta (miss1),Y
#if .byte feuer2=#210
mva #0 feuer1
mva #0 feuer2
lda #0
dey
sta (miss1),y
iny
sta (miss1),y
#end
#end
;-------------------------------------------------------------
;---------- Abfrage Feuerknopf und Routine Schuss links-------
#if .byte strig0<#1 .and feuer3=#1
#if .byte feuer2=#0 .or .byte feuer2>#180
mva #1 feuer4
mva #0 feuer3
lda xposp1
adc #13
sta p1pf
lda yposp1
adc #9
sta feuer5
#end
#end
#if .byte feuer4=#1
ldy feuer5
lda #0
sta (miss1),y
iny
sty feuer5
iny
lda #12
sta (miss1),Y
#if .byte feuer5=#210
mva #0 feuer4
mva #0 feuer5
lda #0
dey
sta (miss1),y
iny
sta (miss1),y
#end
#end
;-------------------------------------------------------------
@
pla
tax
pla
jmp xitvbv ;vb-interrupt wird über xitvbv beendet!!
; -------------------------------------------------------------------------------------
kollision
lda #22
sta delay
jsr wartes
rts
; -------------------------------------------------------------------------------------
umschalten
ldy #4 ;Bildschirme umschalten von unsichtbar auf sichtbar
mva sdlstl var5
mva sdlstl+1 var5+1
lda var1
sta (var5),y
iny
lda var1+1
sta (var5),y
rts
; -------------------------------------------------------------------------------------
wartes
clc
ldx delay ; Warteschleife
st lda RTCLOK+2
wa cmp RTCLOK+2
beq wa
dex
bpl st
rts
; -------------------------------------------------------------------------------------
feinscroll
ldy #1
mva #0 delay
@ jsr wartes
sty vscrol
iny
cpy #8
bne @-
rts
; --------------------------------------------------------------------------------------
grobscroll
;Den Bildschirm um eins hoch / Grobscrolling um eine Zeile
ldx #22
@ ldy #$28
clc
@ mva (var1),y (var2),y
dey
bpl @-
clc
lda var1
adc #$28
sta var1
bcc @+
inc var1+1
@ clc
lda var2
adc #$28
sta var2
bcc @+
inc var2+1
@ clc
dex
bpl @-3
rts
; -------------------------------------------------------------------------------
displaylist
; initialisiere die Displaylist
mva sdlstl var5
mva sdlstl+1 var5+1
ldy #0
clc
@ lda dlist,y
sta (var5),y
iny
cpy #34
bne @-
rts
; ---------------------------------------------------------------------------------------
letztereihe
;Die letzte Reihe printen
;Start der letzten Reihe bei var1 - Line 22
lda var1
adc #112
sta var1
inc var1+1
inc var1+1
inc var1+1
ldy #0
clc
lda (var6),y ;Boarder1 holen
sta var5 ;Boarderanzahl in var5 speichern
lda var6
adc #1
sta var6
ldy #0
lda var6+1
adc #0
sta var6+1
lda (var6),y
ldy var5
@ sta (var1),y ;Boarder1 printen
dey
bpl @-
clc
lda var6
adc #1
sta var6
ldy #0
lda var6+1
adc #0
sta var6+1
lda (var6),y ;Rand Boarder1 holen
inc var5 ;Zeilenzähler eins weiter
ldy var5
sta (var1),y ;Rand Boarder1 printen
clc
lda var6
adc #1
sta var6
ldy #0
lda var6+1
adc #0
sta var6+1
lda(var6),y ;leer holen
tax
lda #0
ldy var5
@ iny
sta (var1),y ; leer printen
dex
bpl @-
sty var5 ;Zeilenzähler sichern
clc
lda var6
adc #1
sta var6
ldy #0
lda var6+1
adc #0
sta var6+1
lda(var6),y ;Rand Boarder2 holen
ldy var5
iny
sty var5
sta (var1),y ;Rand Boarder2 printen
clc
lda var6
adc #1
sta var6
ldy #0
lda var6+1
adc #0
sta var6+1
lda(var6),y ;Boarder2 holen
tax ;Boarderanzahl in x speichern
clc
lda var6
adc #1
sta var6
ldy #0
lda var6+1
adc #0
sta var6+1
lda (var6),y
ldy var5
@ iny
sta (var1),y ;Boarder2 printen
dex
bpl @-
clc
lda var6
adc #1
sta var6
ldy #0
lda var6+1
adc #0
sta var6+1
mva #0 vscrol
rts
; ------------------------------------------------------------------------------
run main
zu zu implementierende Landschaft (lands.asm) und Die Charaktertabelle (character.asm) sind noch unverändert!
Wenn erwünscht (für die, die nicht mit Eclipse arbeiten) kann ich auch eine kurze mov -Datei hochstellen ....
Gruß Peter
Hallo!
Sind diese "Grafikfehler" bei Dir auch, oder habe ich den Programmcode falsch übernommen?

Grüße
Meine Projekte findest Du hier...
nimm mal für lands.asm diesen Code:
;@com.wudsn.ide.asm.mainsourcefile=test1.asm
lands .byte 8,2,8,19,10,9,2
.byte 9,2,8,18,10,12,2
.byte 9,2,8,17,10,13,2
.byte 9,2,8,16,10,14,2
.byte 9,2,8,15,10,16,2
.byte 9,2,8,14,10,17,2
.byte 9,2,8,13,10,17,2
.byte 10,2,8,12,10,17,2
.byte 11,2,8,11,10,18,2
.byte 12,2,8,10,10,17,2
.byte 13,2,8,10,10,15,2
.byte 14,2,8,10,10,14,2
.byte 14,2,8,10,10,14,2
.byte 13,2,8,11,10,14,2
.byte 13,2,8,11,10,14,2
.byte 12,2,8,12,10,14,2
.byte 11,2,8,12,10,15,2
.byte 13,2,8,11,10,14,2
.byte 13,2,8,11,10,14,2
.byte 12,2,8,12,10,14,2
.byte 11,2,8,12,10,15,2
.byte 8,2,8,19,6,8,2
.byte 9,2,8,18,10,11,2
.byte 9,2,8,17,10,12,2
.byte 9,2,8,16,10,13,2
.byte 9,2,8,15,10,15,2
.byte 9,2,8,14,10,16,2
.byte 9,2,8,13,10,17,2
.byte 10,2,8,12,10,17,2
.byte 11,2,8,11,10,18,2
.byte 12,2,8,10,10,17,2
.byte 13,2,8,10,10,15,2
.byte 14,2,8,10,10,14,2
.byte 14,2,8,10,10,14,2 ;34
.byte 13,2,8,11,10,14,2
.byte 13,2,8,11,10,14,2
.byte 12,2,8,12,10,14,2
.byte 11,2,8,12,10,15,2
.byte 13,2,8,11,10,14,2
.byte 13,2,8,11,10,14,2
.byte 12,2,8,12,10,14,2
.byte 11,2,8,12,10,15,2
.byte 12,2,8,10,10,17,2
.byte 13,2,8,10,10,15,2
.byte 14,2,8,10,10,14,2
.byte 14,2,8,10,10,14,2
.byte 13,2,8,11,10,14,2
.byte 13,2,8,11,10,14,2
.byte 12,2,8,12,10,14,2
.byte 11,2,8,12,10,15,2
.byte 13,2,8,11,10,14,2
.byte 13,2,8,11,10,14,2
.byte 12,2,8,12,10,14,2
.byte 11,2,8,12,10,15,2
.byte 13,2,8,11,10,14,2
.byte 13,2,8,11,10,14,2
.byte 12,2,8,12,10,14,2
.byte 11,2,8,12,10,15,2
.byte 13,2,8,11,10,14,2
.byte 13,2,8,11,10,14,2
.byte 12,2,8,12,10,14,2
.byte 11,2,8,12,10,15,2
.byte 11,2,8,12,10,15,2
.byte 13,2,8,11,10,14,2
.byte 13,2,8,11,10,14,2
.byte 12,2,8,12,10,14,2
.byte 12,2,8,12,10,14,2
.byte 12,2,8,12,10,14,2 ;68
du hast wohl noch den älteren Code für lands.asm ... bislang habe ich nur eine Testlandschaft drin, die sich dann wiederholt. Daran werde ich jetzt aber relativ zeitnah dran arbeiten. Vorher muss ich aber noch etwas am Player arbeiten und die Kollisionen müssen noch rein!
Perfekt! Danke.
Meine Projekte findest Du hier...
soo ich habe den Antrieb drin und die Blinklichter…
... da meine Frau bis Donnerstag auf Achse ist und ich heute erst ab 15 Uhr zu arbeiten anfange, habe ich ein wenig Zeit zu programmieren...
Den Antrieb vom Raumschiff habe ich etwas angepasst und dabei festgestellt, dass der VBI so langsam ausgereizt ist. Daher habe ich jetzt noch schnell die Kollisionsabfragen für das Raumschiff und die beiden Schüsse in den VBI programmiert. Die beiden Schüsse laufen wie gewohnt nach ganz unten durch wenn keine Barriere im Weg ist, treffen die Schüsse auf die Landschaft, verschwinden sie einfach. Wenn bestimmte Ziele getroffen werden, passiert eine bestimmte Aktion.... das folgt dann bald! Ich habe jetzt einen Player für das Raumschiff und einen für den Antrieb benutzt, zwei Missile für die beiden Schüsse und zwei Missile fürs Blinken. Das läuft jetzt recht stabil, ab und zu passiert mal ein kleiner Grafikfehler, den ich noch nicht entdeckt habe. Später..... Ich bin mir aber noch nicht so ganz sicher, ob ich das nochmal umprogrammieren muss... vielleicht baue ich später das Blinken um und nutze dafür einen Player - die beiden gesparten Missile nutze ich dann für 4 statt 2 Schüsse. Auch mit dem Aufbau der Schüsse bin ich nicht so ganz zufrieden, das muss ich nochmal grundsätzlich umprogrammieren, damit alles etwas schlanker und besser läuft... Aber so wie es jetzt ist, funktioniert schon alles recht gut und ich baue jetzt erstmal die Landschaft aus. Auch hier muss ich etwas umprogrammieren, denn der Aufbau der letzten Reihe (hier wird ja die Landschaft kontinuierlich aus den Datensätzen gebildet) beinhaltet noch nicht die Items, die das Raumschiff abschießen soll/muss. Das gehe ich jetzt als nächstes an! Gruß Peter
... die Character habe ich angepasst - ein erstes "Item" ist fertig, nämlich der FUEL-Tank
... die Landschaft habe ich etwas erweitert: Statt 7 Bytes sind jetzt 9 Bytes pro Reihe hinterlegt, die letzten beiden Bytes legen in einer Reihe fest, welches Item an welcher Position geprintet wird - drei Tanks habe ich bereits integriert in die Landschaft, die ich entsprechend auch vergrößert habe...
... die letzte Reihe habe ich entsprechend angepasst, die Items werden jetzt erkannt (sofern in der Landschaft hinterlegt) und geprintet...
Gruß und ein schönes WE
Am WE wollte ich mal kurz die Schusskollision weiter entwickeln und die entsprechende Explosion des Items (der Öltank) einfügen. Leider habe ich hier massive Schwierigkeiten auf mehreren Ebenen bekommen. Zunächst wollte ich die Kollisionsabfrage im VBI machen und im Hauptprogramm dann die weiteren Schritte der Erkennung der genauen Position und dann die Explosion einfügen. Beides funktionierte zunächst nicht so richtig und ich dachte, es müsse auch in den VBI komplett mit rein. Das habe ich dann auch umgesetzt - und dabei feststellen müssen, daß er die Kollision nicht immer erkennt - ein Muster habe ich dabei nicht evaluieren können... dann kam noch die Schwierigkeit, die genaue Position des Tanks mit dem Missile zu koordinieren. Das ist in meinem Programm nicht so einfach, da der Missile eine volle Positionsauflösung hat und die Landschaft aus Charactern (8bit) aufgebaut ist. Ich muss also die x- und y-Position der Missiles zunächst umrechnen (teilen durch 8 in y und teilen durch 4 in x) und kämpfe noch mit einem Rundungsfehler.... das Teilen durch 8 geht mit drei ROR-Anweisungen! Am Ende ist das Timing und wohl auch der Zusatzcode im VBI zu lang und gestern endlich kam der Durchbruch, wo ich es stabil geschafft habe, den Code für die Explosion im Hauptprogramm unterzubringen - im VBI gibt es zu viele Timing-Probleme. Mein nächstes Projekt werde ich ganz anders strukturieren - das steht schon fest. Auch werde ich dann wohl mit einer ganz anderen Auflösung und Matrix arbeiten - das bringt zwar mehr Probleme was Speicher und Scrolling angeht, erleichtert aber mutmaßlich viele andere Dinge....
Ich frage mich auch zunehmend, ob es Sinn macht, den Code hier reinzustellen, denn der wird immer umfangreicher und unübersichtlicher trotz der Kommentare. Hier hätte ich gerne ein kurzes Feedback...
Liebe Grüße Peter
Moin!
Spontan würde ich vorschlagen auf Github den Quellcode zu posten. Dort lägen dann immer alle aktuellen Files die Du nutzt und man kann jederzeit sich dieses herunterladen. Jedoch kenne ich mich mit Github nicht aus, ob und wie schwer es ist dort den Code hochzuladen.
Ansonsten hätte ich schon Interesse an den Quellcode. Die Kollision und vorallem die Identifizierung des getroffenen Objekts würden mich sehr interessieren 🙂
Der Quellcode kann nicht genug Remarks enthalten... dass merkt man aber erst, wenn man selber nach 3-4 Monaten etwas sucht 😁
Grüße Janko
Meine Projekte findest Du hier...
... mit Github kenne ich mich auch nicht so aus ...ich denke mal darüber nach! Mit den Remarks hast du absolut Recht! Da muss ich noch viel mehr machen!!
Das Objekt nach der Kollision zu identifizieren geht jetzt ganz gut! Du hast ja die x- und y-Position des Missile zum Zeitpunkt des Treffers. Diese Werte auslesen und sichern.
Wenn du - so wie in diesem Projekt - mit Graphics 0 arbeitest (Zeile hat 40 Character a 8 Bit und Spalte hat 24 Character a 8 Bit), dann musst du für die x-Position des Missile zunächst 48 subtrahieren und dann mittels
Ich habe jetzt tatsächlich gerade eben mir die Mühe gemacht die Ränder abzufragen und entsprechend dann die Position zu korrigieren:
dey
lda (var2),y
sta var8
iny
iny
lda (var2),y
sta var9
dey
dey
#if .byte var8=#0 .and .byte var9>#0
iny
#end
#if .byte var8>#0 .and .byte var9=#0
dey
#end
lda #45
sta (var2),y
iny
sta (var2),y
iny
sta (var2),y
in var2 steht die Bildschirmadresse mit bereits korrekter y-Position in y steht die x-Position beim Treffer des Missiles nach Korrektur (-48 /4) in var8 geht der rechte Rand rein in var9 geht der linke Rand rein entsprechend verschiebe ich die x-Position um eins nach rechts oder links - oder gar nicht (mein Objekt ist 3 breit). Lda#45 ist nur eine Hilfszahl - später baue ich hier die Explosion rein!!
jetzt habe ich noch den y-Wert - also die vertikale Position der Kollision abgefragt und entsprechend korrigiert. Die Position am Item - also da wo die Explosion des Items bei Kollision mit dem Schuss stattfinden soll ist jetzt immer definiert und an gleicher Stelle - dafür habe ich jetzt tatsächlich erheblich Zeit und Code verwendet und frage mich natürlich, ob das nicht viel viel einfacher geht... bestimmt!! Aber egal, dieser Code und die entsprechende Logik stammt von mir und - hurra - funktioniert tadellos! Nach ca. 4 Tagen verzweifelten Kampfes 😉 Der Subroutinencode:
kollitem
;var8 unveränderter Bildschirmanfang
lda yschuss1 ;in Gr.0 -32 (sichtbarer Bereich ab 32 und /8
sec
sbc #32
clc
ror
clc
ror
clc
ror
sta yschuss1 ;y-Position in das x-Register schreiben
tax
dex ; und einen abziehen
lda xschuss1 ;x-Position -48 (sichtbarer Bereich)und /4
sec
sbc #48
clc
ror
clc
ror
tay ;in y geht die x-Position
sec
mva var1 var2 ;holen der Bildschirmadresse -> var2
mva var1+1 var2+1
clc
@
lda var2 ;jetzt die y-Position auf die richtige Höhe stellen
adc #40
sta var2
lda var2+1
adc #0
sta var2+1
dex
bpl @- ;die y-Position steht in x - Addition von x Zeilen
@
dey ;die korrekte x-Position einstellen
lda (var2),y ;linken Rand checken
sta var8
iny
iny
lda (var2),y ;rechten Rand checken
sta var9
dey
dey
#if .byte var8=#0 .and .byte var9>#0 ;Position nach rechts anpassen
iny
#end
#if .byte var8>#0 .and .byte var9=#0 ;Position nach links anpassen
dey
#end
lda (var2),y ;2. Durchgang der Anpassung um letzte
sta var8 ;Fehler zu beseitigen
iny
iny
lda (var2),y
sta var9
dey
dey
#if .byte var8=#0 .and .byte var9>#0
iny
#end
#if .byte var8>#0 .and .byte var9=#0
dey
#end
lda (var2),y ;Korrektur der y-Position
sta var8 ;in var8 aktuelle BS-Position
sec
lda var2 ;eins drüber - bleibt wenn var2 zu tief
sbc #40
sta var2
lda var2+1
sbc #0
sta var2+1
lda (var2),y ;lade Bildschirminhalt eins drüber
sta var9 ;das geht in var9 rein
#if .byte var8>#0 .and .byte var9=#0 ;alte Position var2
clc ;wiederherstellen
lda var2
adc #40
sta var2
lda var2+1
adc #0
sta var2+1
#end
#if .byte var8=#0 .and .byte var9=#0 ;alte Position var2
clc ;eins runter
lda var2
adc #80
sta var2
lda var2+1
adc #0
sta var2+1
#end
lda (var2),y ;2. Durchgang der Anpassung um letzte
sta var8 ;Fehler zu beseitigen
sec
lda var2
sbc #40
sta var2
lda var2+1
sbc #0
sta var2+1
lda (var2),y
sta var9
#if .byte var8>#0 .and .byte var9=#0
clc
lda var2
adc #40
sta var2
lda var2+1
adc #0
sta var2+1
#end
#if .byte var8=#0 .and .byte var9=#0
clc
lda var2
adc #80
sta var2
lda var2+1
adc #0
sta var2+1
#end
;ab hier stimmt die Position des Items
;in der Variable y für x-Position
;und in var2 für die y-Position
lda #45
sta (var2),y
iny
sta (var2),y
iny
sta (var2),y
mva #2 hitclr
mva #0 kollm1
rts
Dieser Code funktioniert auch für alle Kollisionen und steht entsprechend als Subroutine... was folgt jetzt: Bislang habe ich ja nur eine Dreierreihe als Simulation der Explosion geprintet - jetzt kommt die komplette Überschreibung des Items und dann die Animation dieser Explosionswolke... Ich überlege noch, ob ich das folgendermaßen mache: Entweder printe ich hintereinander verschiedene Werte in das Gebiet des Items - so daß es animiert aussieht. Oder ich lösche das Items komplett und überlagere das Gebiet mit Player4, der selber eine Animation einer explodierenden Wolke darstellt. Problem hierbei ist, wenn ich mehrere Explosionen gleichzeitig darstellen muss.
Hallo!
Ich habe mal gehört (gefährliches Halbwissen), dass man Berechnungen möglichst vermeiden sollte.
So würde man eine Tabelle mit 40 Werten nehmen wo immer der erste Wert für Gr. 0 -X drin steht. Also z.B. 48, 52, 56, 60... und nun vergleicht man den X-Wert des Missels mit der Tabelle. Bei Position 5 ein Match also ist im X-Wert eine 5 für Gr. 0. Das gleiche macht man im Y-Bereich und erhält eine Wandlung der X/Y- Spriteposition zu X/Y-Gr.0-Position. Eine Schleife mit einem kleinem Vergleich soll wohl schneller sein also eine Berechnung.
Aber wie gesagt, ich weiß es selbst nicht wirklich.
Grüße Janko
Meine Projekte findest Du hier...
Hi Janko, vielen Dank für diesen Hinweis - in der Tat habe ich über genau so eine Tabelle auch nachgedacht und hätte das auch so gemacht. Teilen durch 4 bzw. 8 erschien mir aber machbar durch einfache Bitrotation und funktioniert auch ganz gut. Die Größe der Tabelle hat mich etwas abgeschreckt!!
Was dann heute als echter Pferdefuss noch auftrat war dann die Tatsache, dass mein Item (also zB der Tank) ja deutlich breiter ist, als mein Schuss und ich also gar nicht so genau weiß, wo mein Schuss gelandet ist - es sei denn (fällt mir gerade zur Sekunde als Idee ein) ich gestalte die Oberfläche des Items von der Farbe her unterschiedlich - dann bekomme ich einen jeweils anderen Wert für die Kollision und kann das auch nutzen... nun ja, jetzt habe ich die entsprechenden Abfragen aufwendig programmiert und es funktioniert stabil - lass ich jetzt mal!!
Für das nächste Projekt werde ich das direkt etwas anders konzipieren....
... weiter gehts mit meinem Projekt! Ich stelle auf Gr. 7 mit 4 Farben um und werde zunächst die Landschaft anpassen müssen. Hier mal ein erstes Video mit dem Vergleich: Neu links und Alt rechts.... Die Landschaft links ist natürlich hinsichtlich Form und Farbe noch nicht angepasst, sehr schön kann man hier aber den direkten Vergleich sehen zwischen Gr.0 40x24 Textgrafik (980 Bit) zu Gr.7 40x80 Bitmapgrafik (3200)
Vorweihnachtszeit = viel Arbeit = wenig Zeit zum programmieren... Aber ich habe heute mich um die Farben gekümmert und bin dabei das Programm auf die neue Grafik umzustellen.
Das wird jetzt recht aufwendig, da doch einiges an Code komplett neu muss. Ich will den Bildschirm in 16x16 Byte Blöcken einteilen, dabei brauche ich dann für einen kompletten Bildschirm nur einen Speicherbedarf von 200 Byte bei einer Auflösung von 160x80 mit 4 Farben. Das schafft die CPU noch ganz gut zu scrollen und sieht flüssig aus. Die Matrix wird dann praktisch 20x10 sein und in dieser Matrix sind dann die Bildschirmdaten hinterlegt, die auf den sichtbaren Bildschirm zu printen sind. Beim Printen passiert direkt das scrolling... mit einem Interrupt kann ich z.B. ständig die Matrix ändern und so Teile des Bildschirms animieren... so der Plan! Hoffentlich überlaste ich den Rechner damit nicht 😉 Wir werden sehen.... wenn es geht, könnte das recht cool werden...
Anbei noch der aktuelle Stand, wo aber die Landschaft noch nicht wesentlich angepasst ist - hier läuft zunächst noch eine Testlandschaft, die sich wiederholt. Auch die Items sind noch nicht angepasst. Viel Arbeit noch 😉 aber ich habe ja Zeit....
LG und ein frohes Fest uns allen!! Peter
... gerade habe ich nun die FUEL-Tanks optisch angepasst und die komplette Animation der Explosion generiert. Dafür brauche ich 3x12 = 36 Charakter! Nun grübel ich allerdings schon seit Tagen, wie ich diese Explosion am besten umsetze. Eine richtig einfache Lösung habe ich noch nicht gefunden - ein denkbarer Ansatz, den ich gerade verfolge ist relativ aufwendig zu programmieren. Vorweg: Einfach die Charakter ändern geht nicht, denn dabei würden sich ja dann z.B. alle Tanks entsprechend animieren - also explodieren und nicht nur der, der getroffen wurde. Es hilft nichts: Ich muss die Kollision abfragen, die ganz genaue Position des getroffenen Tanks bestimmen, diesen dann mit der ersten Explosionssequenz überschreiben, beim scrolling muss ich die Position des Tanks entsprechend weiterschreiben, damit die 2. und 3. und dann 4. Sequenz der Explosion auf die entsprechende Stelle geschrieben werden kann. Das muss ja auch 2-4 x zugleich auf dem Bildschirm ablaufen können, denn man kann ja mehr als immer nur einen Tank bzw. Item treffen. Vielleicht hat jemand hier noch eine bessere Idee...
Hier noch eine mov-Datei mit dem aktuellen Stand... Sobald ich den Code für die Explosion drin habe, kommen die nächsten Items und dann baue ich die Landschaft weiter. Dann stelle ich auch wieder den aktuellen Code rein! Allen eine frohe Weihnacht und bis bald! Gruß Peter
Da Du nun doch den Charmode nutzt...
Für die Explosionen nutze nicht einfach 36 Zeichen, sondern nutze nur die Zeichen, die für denTank nötig sind. Die Explosion wird dann erzeugt, indem die entsprechenden Zeichen mit dem neuen Werten direkt verändert werden. So äußerst Du Platz im Font für möglichst viele Sachen.
Aber Du musst dann natürlich mehr Dinge kopieren.
PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo
hmmmm.... also ein Tank besteht bei mir aus 4 Reihen a 3 Character - also insgesamt 12 Character für den Öltank. Der Öltank ist das größte Item - die Explosion muss also auch 12 Character haben, animiert 3x12 also 36. Klar könnte ich das mit 12 machen und die Phasen reinkopieren - gute Idee - das Problem ist dann aber wenn ich (und das kommt vor) zwei oder sogar 3 Items abballere, die dann auch in unterschiedlichen Phasen explodieren und dabei auch noch hochgescrollt werden müssen weil das Spiel ja weiterläuft. Da hänge ich gerade.... Jede Lösung erscheint von nicht unerheblichen Programmieraufwand. Da warte ich noch auf die Eingebung, wie ich das viel leichter lösen kann ...
Hallo!
Ich weiß nicht wieviel Platz Du noch in Deinem Char-Set hast, aber Du könntest festlegen, dass nur 4 Tanks gleichzeitig vorhanden sein dürfen und vergibst für jeden Tank dann seine eigenen Zeichensequenz. So musst Du 48 Zeichen für 4 Tanks vorhalten, kannst dann aber jeden der 4 Tanks einzeln animieren.
Grüße Janko
Meine Projekte findest Du hier...
daran habe ich auch schon gedacht, aber ich werde nicht nur Tanks haben, sondern noch weitere Items - und dann wird es irgendwann knapp im Zeichensatz! Ich habe ja nur 128...
Ja, aber wenn nur 4 Items gleichzeitig sichtbar sind, kannst Du mit den Zeichen auch andere Items darstellen. Je nach Scrollposition.
Meine Projekte findest Du hier...
Die letzten Tage habe ich immer wieder an der Explosion gearbeitet - und dabei festgestellt, daß es viel viel schwieriger ist, als gedacht.
Die Animation für eine Explosion ist zunächst völlig ausreichend, da mein Raumschiff gar nicht so oft hintereinander schießen kann - zwei Tanks gleichzeitig zur Explosion zu bringen ist dabei fast unmöglich.
Dann habe ich viel mit dem Timing experimentiert und entweder läuft die Explosion zu schnell ab und man sieht die Phasen gar nicht, oder zu langsam, wenn ich es in den Code aufwendig in verschiedenen Phasen zwischen Feinscroll und Grobscroll integriere. Die Explosion in den VBI zu bringen läuft auch zu schnell - hier könnte man mit ein wenig Programmieraufwand das Zeittiming für die Explosion vielleicht noch besser hinbekommen.
Ich habe es jetzt aber erstmal einfacher gelöst: Die Explosion mit der Animation läuft direkt hintereinander ab mit einem kleinen Zeitdelay, was man leider dann im Spiel merkt, da es während der animierten Explosion zu einem kleinen Stop kommt. Ich lasse das jetzt aber erstmal so und mache endlich mit den anderen Items weiter und vor allem baue ich jetzt die Landschaft weiter aus...
Gruß
Peter
ich war fleißig, auch wenn man es vielleicht nicht so sehr sieht!! Zunächst habe ich die Explosion implementiert, die Landschaft und die Charakter weiter ausgebaut - hier fehlen noch ein paar Landschaftsteile. Dann habe ich die Anzeige mit Titel, Score, Fuel incl. Laufleiste für den Fuel implementiert. Ich musste den Aufbau der letzten Reihe erweitern, was mich viel Schweiß gekostet hat - das war nötig weil ich die Randbegrenzung komplettieren wollte / musste. Danach hatte ich ganz unerklärliche Ruckelartefakte - daran habe ich jetzt fast 2 Tage gesessen... ich dachte schon, daß die CPU langsam an die Grenze kommt und der VBI Störartefakte reinhaut... alles musste runterreduziert werden, ohne Erfolg. Am Ende war es die Displaylist. Eine kleine Anpassung und der Ruckler war wieder raus ... omG !!!! Programmieren ist manchmal wie ein Krimi. Jetzt baue ich so langsam die Landschaft weiter aus - wie man sieht auf dem Video gibt es noch eine Menge an kleineren Fehlern. Warum nur bekomme ich diesen grünen Balken links zusätzlich rein... Der Code wird immer länger und unübersichtlicher trotz Dokumentation... noch komme ich aber klar! Aber jetzt bloß keine zu lange Pause machen. Ich stelle gerne den gesamten Code hier online und wer möchte kann selber daran rumfummeln... ob jemand da aber noch durchsteigt .. keine Ahnung!! Jetzt noch eine kleine mov - Datei - und wie gesagt: Bei Interesse stelle ich den Code hier rein! Es ist noch viel zu tun.... 😉
Mach das mal mit dem Code. Dann kann ich Dir vielleicht helfen dass Du wieder einen einfacheren Durchblick bekommst.
PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo
here we go... 😉
Hauptprogramm:
org $2000
icl '../hardware.txt'
icl '../header.txt'
icl 'character.asm'
icl 'lands.asm'
dlist .byte 112,112,112,100
.byte 30,75
.byte 36,36,36,36,36,36,36,36,36,36,36,36
.byte 36,36,36,36,36,36,36,36,36,4,4,4,4,4
.byte 65,32,156
pm1 .byte 0,24,60,36,36,126,126,255,219,219,129,129,129,0
pm41 .byte 0,28,28,8,8,0,4,0,0,0,0,0,0,0
.byte 0,28,28,24,8,8,4,4,0,0,4,0,8,0
.byte 0,28,24,28,24,8,4,8,8,4,0,0,0,0
mi1 .byte 3,3,3,3
mi2 .byte 12,12,12,12
mi3 .byte 12,12,12,12
mi4 .byte 12,12,12,12
.proc main
main1 jsr displaylist ;Subroutine Displaylist-Aufbau
mva #30 yposp1
mva #120 xposp1
mva #42 yposm1
mva #0 xposm1
mva #94 yposm2
mva #100 xposm2
mva #0 tank1x
mva #0 tank1y
mva #151 fuelzaehleritem
mva #0 fuelzaehler
jsr text
Start1 mva #>chr chbas ;HighByte Character Pointer auf $2000 setzen
mva #192 gprior ;GTIA Modus 3
mva #15 color3 ;Schriftfarbe
mva #218 color1 ;Gelb
mva #154 color0 ;Blau
mva #52 color2 ;Rot
mva #180 color2 ; Grün
mva #0 color4 ;Hintergrundfarbe
lda #0 \ tax \ sta var3 \ sta var4 \ sta var6 \ sta var7 \ sta var6+1
; Player vorbereiten und initialisieren
lda ramtop
sec
sbc #16
sta pmbase
clc
adc #3
sta miss1+1
adc #1
sta play1+1
adc #3
sta play4+1
lda #9
sta play4
mva #62 sdmctl
mva #56 pcolr0
mva #56 pcolr1
mva #142 pcolr2
mva #142 pcolr3
mva #1 gprior
mva #3 gractl
mva #1 sizep0
mva #1 sizep1
mva #0 sizem
mva #0 rechts
mva #2 hitclr
mva #48 blink
main2 mva <lands var6
mva >lands var6+1
mva #0 kollp0
ldy #255 ;Speicher Player 1 leeren
lda #0
sta play1
@ sta (play1),y
sta (play4),y
dey
bpl @-
clc
ldy yposp1 ;verticale Startpos. Player 1 + füllen
ldx #0
@ lda pm1,x
sta (play1),y
;lda pm41,x
;sta (play4),y
iny
inx
cpx #14
bne @-
clc
ldy #0
ldx #0
@ lda mi1,x
sta (miss1),y
iny
inx
cpx #2
bne @-
lda xposm1
sta p0pf
lda xposm2
sta p1pf
ldx #>vbinter ;VB-Interrupt VektorHi
ldy #<vbinter ;VB-Interrupt VektorLo
lda #7 ;Deferred Mode mit lda #7 festlegen
jsr setvbv ;Vektor für die eigene Routine über setvbv eintragen
hauptprogramm
clc
lda kollp0
cmp #1
bcc @+
jsr kollision
mva #0 kollp0
@ jsr letztereihe ;letzte Reihe (lands) Bildschirm1 printen (sichtbar)
jsr feinscroll ;Feinscroll Bildschirm1 ausführen (sichtbar)
mva #$30 var1 ;var1 auf 30000 ($7530) setzen
mva #$75 var1+1
mva #$E4 var2 ;var2 auf 31460 ($7AE4) setzen
mva #$7A var2+1
jsr grobscroll ;Bildschirm1 kopieren + grobscroll
mva #$0C var1 ;var1 + var2 auf 31500 ($7B0C) setzen
mva #$0C var2
mva #$7B var1+1
mva #$7B var2+1
jsr umschalten
inc fuelzaehleritem
lda fuelzaehler
tax
lda fuelzaehleritem
sta 31043,x
sta 32543,x
#if .byte fuelzaehleritem=#155
mva #151 fuelzaehleritem
inc fuelzaehler
#end
#if .byte fuelzaehler>#200
mva #0 fuelzaehler
#end
#if .byte fuelzaehler=#20
mva #52 color3
#end
#if .byte fuelzaehler>#34 .and .byte fuelzaehler<#200
jmp main1 ;Fuel zuende Neustart
#end
mva #0 kollm1
mva #0 kollm2 ;umschalten auf Bildschirm2 - Bildschirm2 wird sichtbar
jsr letztereihe
jsr feinscroll ;Feinscroll Bildschirm2 ausführen (sichtbar)
mva #$08 var2 ;var1 auf 29960 ($7508) setzen
mva #$75 var2+1
mva #$0C var1 ;var2 auf 31500 ($7B0C) setzen
mva #$7B var1+1
#if .byte kollges=#4
mva #15 color3
sec
lda fuelzaehler
sbc #10
sta fuelzaehler
tax
mva #151 fuelzaehleritem
clc
lda fuelzaehleritem
@ sta 31043,x
sta 32543,x
inx
cpx #36
bne @-
jsr kollitem
mva #0 kollges
#end
mva #$08 var2 ;var1 auf 29960 ($7508) setzen
mva #$75 var2+1
mva #$0C var1 ;var2 auf 31500 ($7B0C) setzen
mva #$7B var1+1
jsr grobscroll ;;Bildschirm2 kopieren + grobscroll
mva #$30 var1 ;var1 + var2 auf 30000 ($7530) setzen
mva #$30 var2
mva #$75 var1+1
mva #$75 var2+1
;mva #1 delay
jsr umschalten ;umschalten auf Bildschirm1 - Bildschirm1 wird sichtbar
inc fuelzaehleritem
lda fuelzaehler
tax
lda fuelzaehleritem
sta 31043,x
sta 32543,x
#if .byte fuelzaehleritem=#155
mva #151 fuelzaehleritem
inc fuelzaehler
#end
;Ende der Bildschirmausführung / Kontrolle Durchläufe
sec
lda #40 ; - 36 = Anzahl der Durchläufe - auf 4 beschränkt, da die Landschaft noch rudimentär ist und sich dann wiederholen soll
sbc var6+1
bpl @+
jmp start1 ;Stop hier
@
jmp hauptprogramm ;weiter
.endp
; _____________________________________________________________________________________
;
; ---------------------------- S U B R O U T I N E N ----------------------------------
; _____________________________________________________________________________________
;vertical blank interrupt für Joystick / PM
vbinter
pha
txa
pha
mva #0 atract ;Bildschirmschoner aus
inc blink
lda blink2
adc #20
sta blink2
clc ;Kollisionen abfragen
lda p0pf
cmp #1
bcc @+
mva #1 kollp0
@
clc ;Joystickabfragen Player1
lda stick0
cmp #15 ;keine Joystickaktion
bcs @+
cmp #14
bcs nachob
cmp #13
bcs nachun
cmp #11
bcs nachli
cmp #10
bcs nachliob
cmp #9
bcs nachliun
sec
cmp #7
bcs nachre
cmp #6
bcs nachreob
cmp #5
bcs nachreun
@ jmp write
nachre clc
lda xposp1
cmp #192
bcs @+
inc xposp1
@ jmp write
nachreun
clc
lda xposp1
cmp #192
bcs @+
inc xposp1
@ jmp nachun
nachreob
clc
lda xposp1
cmp #192
bcs @+
inc xposp1
@ jmp nachob
nachli sec
lda xposp1
cmp #49
bcc @+
dec xposp1
@ jmp write
nachliun
sec
lda xposp1
cmp #49
bcc @+
dec xposp1
@ jmp nachun
nachliob
sec
lda xposp1
cmp #49
bcc @+
dec xposp1
@ jmp nachob
nachob
dec yposp1
clc
ldy yposp1 ;verticale Startpos. Player 1 + füllen
ldx #0
@ lda pm1,x
sta (play1),y
iny
inx
cpx #14
bne @-
jmp write
nachun
inc yposp1
clc
ldy yposp1 ;verticale Startpos. Player 1 + füllen
ldx #0
@ lda pm1,x
sta (play1),y
iny
inx
cpx #14
bne @-
jmp write
clc
write
lda xposp1 ;Blinkabschnitt
sta hposp0
adc #2
sta hposp3
#if .byte blink<#64 ;Blink links
ldy yposm3
lda #0
sta (miss1),y
mva hposp0 xposm3
ldy yposp1
lda #48
iny
iny
iny
iny
iny
iny
sta (miss1),y
mva xposp1 p2pf
mva xposp1 xposm3
sty yposm3
#end
#if .byte blink>#63 .and .byte blink<#128 ;Blink rechts
ldy yposm3
lda #0
sta (miss1),y
ldy yposp1
lda #192
iny
iny
iny
iny
iny
iny
sta (miss1),y
lda xposp1
adc #13
sta p3pf
mva xposp1 xposm3
sty yposm3
#end
#if .byte blink>#127 .and .byte blink<#192 ;Blink links
ldy yposm3
lda #0
sta (miss1),y
mva hposp0 xposm3
ldy yposp1
lda #48
iny
iny
iny
iny
iny
iny
sta (miss1),y
mva xposp1 p2pf
mva xposp1 xposm3
sty yposm3
#end
#if .byte blink>#191 .and .byte blink<#255 ;Blink rechts
ldy yposm3
lda #0
sta (miss1),y
ldy yposp1
lda #192
iny
iny
iny
iny
iny
iny
sta (miss1),y
lda xposp1
adc #13
sta p3pf
mva xposp1 xposm3
sty yposm3
#end
;---------- Abfrage Feuerknopf und Routine Schuss links-------
#if .byte strig0<#1 .and .byte feuer3=#0
#if .byte feuer5=#0 .or .byte feuer5>#180
mva #1 feuer1
mva #1 feuer3
mva xposp1 p0pf
mva xposp1 xschuss1
lda yposp1
adc #9
sta feuer2
#end
#end
#if .byte feuer1=#1
ldy feuer2
iny
iny
lda #0
sta (miss1),y
sty feuer2
iny
iny
lda #3
sta (miss1),Y
mva m0pf kollm1
#if .byte kollm1=#4
mva kollm1 kollges
mva feuer2 yschuss1
#end
#if .byte kollm1>#2
mva #211 feuer2
#end
#if .byte feuer2>#210
mva #0 feuer1
mva #0 feuer2
lda #0
sta (miss1),y
#end
#end
;-------------------------------------------------------------
;---------- Abfrage Feuerknopf und Routine Schuss rechts-------
#if .byte strig0<#1 .and feuer3=#1
#if .byte feuer2=#0 .or .byte feuer2>#180
mva #1 feuer4
mva #0 feuer3
lda xposp1
adc #13
sta p1pf
sta xschuss1
lda yposp1
adc #9
sta feuer5
#end
#end
#if .byte feuer4=#1
ldy feuer5
iny
iny
lda #0
sta (miss1),y
sty feuer5
iny
iny
lda #12
sta (miss1),Y
mva m1pf kollm2
mva m1pf kollm2
#if .byte kollm2=#4
mva kollm2 kollges
mva feuer5 yschuss1
#end
#if .byte kollm2>#1
mva #211 feuer5
#end
#if .byte feuer5>#210
mva #0 feuer4
mva #0 feuer5
lda #0
dey
sta (miss1),y
iny
sta (miss1),y
#end
#end
;-------------------------------------------------------------
ldy yposp1
clc
#if .byte blink2>#0 .and .byte blink2<#75
ldx #0
#end
#if .byte blink2>#75 .and .byte blink2<#160
ldx #14
#end
#if .byte blink2>#160 .and .byte blink2<#255
ldx #28
#end
dey
mva #0 lms2
@
lda pm41,x
sta (play4),y
iny
inx
inc lms2
lda lms2
cmp #14
bne @-
mva #2 hitclr
pla
tax
pla
jmp xitvbv ;vb-interrupt wird über xitvbv beendet!!
; -------------------------------------------------------------------------------------
kollision
ldx #0
clc
@ inx
cpx #255
bcc @-
rts
; -------------------------------------------------------------------------------------
umschalten
ldy #4 ;Bildschirme umschalten von unsichtbar auf sichtbar
mva sdlstl var5
mva sdlstl+1 var5+1
lda var1
sta (var5),y
iny
lda var1+1
sta (var5),y
rts
; -------------------------------------------------------------------------------------
wartes
clc
ldx delay ; Warteschleife
st lda RTCLOK+2
wa cmp RTCLOK+2
beq wa
dex
bpl st
rts
; -------------------------------------------------------------------------------------
feinscroll
ldy #1
mva #0 delay
@ jsr wartes
sty vscrol
iny
cpy #8
bne @-
rts
; --------------------------------------------------------------------------------------
grobscroll
;Den Bildschirm um eins hoch / Grobscrolling um eine Zeile
ldx #22
@ ldy #$28
clc
@ lda (var1),y
sta itemex
#if .byte itemex=#68
jsr fuel
#end
sta (var2),y
dey
bpl @-
clc
lda var1
adc #$28
sta var1
bcc @+
inc var1+1
@ clc
lda var2
adc #$28
sta var2
bcc @+
inc var2+1
@ clc
dex
bpl @-3
rts
; -------------------------------------------------------------------------------
displaylist
; initialisiere die Displaylist
mva sdlstl var5
mva sdlstl+1 var5+1
ldy #0
clc
@ lda dlist,y
sta (var5),y
iny
cpy #34
bne @-
rts
; ---------------------------------------------------------------------------------------
letztereihe
;Die letzte Reihe printen
;Start der letzten Reihe bei var1 - Line 22
;in Var6 (+1) wird die Position von lands gespeichert
;in Var5 gehen Infos der Boarderanzahl rein
;in y ist der Zähler für letzte Reihe
;x wird als Zähler fürs printen benutzt
lda var1+1
;sta var8+1
;sta var7+1
lda var1
;sta var8
;sta var7
adc #112
sta var1
inc var1+1
inc var1+1
inc var1+1
ldy #0
clc
lda (var6),y ;Boarderanzahl 1 holen
sta var5 ;Boarderanzahl 1 in var5 speichern
jsr var6up
lda (var6),y ;Boarderart 1 holen
ldy var5 ;Zeilenzählen in y übertragen
@ sta (var1),y ;Boarder1 printen
dey
bpl @-
jsr var6up
adc #0
sta var6+1
lda (var6),y ;Boarderanzahl 2 holen
tax
jsr var6up
lda (var6),y ;Boarderart 2 holen
ldy var5
@ iny
sta (var1),y ;leer printen
dex
bpl @-
sty var5 ;Zeilenzähler sichern
jsr var6up
lda (var6),y ;Rand Boarder2 holen
inc var5 ;Zeilenzähler eins weiter
ldy var5
sta (var1),y ;Rand Boarder1 printen
jsr var6up
inc var5
lda(var6),y ;leer holen
tax
lda #0
ldy var5
@ iny
sta (var1),y ;leer printen
dex
bpl @-
sty var5 ;Zeilenzähler sichern
jsr var6up
lda(var6),y ;Rand Boarder3 holen
ldy var5
iny
sty var5
sta (var1),y ;Rand Boarder3 printen
jsr var6up
lda(var6),y ;Boarder4 holen
tax ;Boarderanzahl in x speichern
jsr var6up
lda (var6),y
ldy var5
@ iny
sta (var1),y ;Boarder4 printen
dex
bpl @-
sty var5 ;Zeilenzähler sichern
jsr var6up
lda(var6),y ;Boarder5 holen
tax ;Boarderanzahl in x speichern
jsr var6up
lda (var6),y
ldy var5
@ iny
sta (var1),y ;Boarder5 printen
dex
bpl @-
jsr var6up
lda (var6),y ;Sonderitem holen
sta var5 ;Item in Var5 speichern
jsr var6up
#if .byte var5=#56 ;Öltank printen
#if .byte tank1x=#0
mva var1 tank1y
mva var1+1 tank1y+1
sec
lda tank1y
sbc #120
sta tank1y
lda tank1y+1
sbc #0
sta tank1y+1
#end
lda (var6),y ;Startposition des Items in y speichern
sta tank1x
tay
jsr fuel ;Fueltank printen
#end
jsr var6up
mva #0 vscrol
sec
lda tank1y
sbc #40
sta tank1y
lda tank1y+1
sbc #0
sta tank1y+1
lda tank1x
tay
mva #0 var5
rts
var6up clc
lda var6
adc #1
sta var6
ldy #0
lda var6+1
adc #0
sta var6+1
rts
; --------------------------------------------------------------------------------------
fuel sec ;Routine um den Öltank zu printen - es werden 12 Character meanderförmig geprinten 3x4 Matrix
lda var1
sbc #160
sta var2
lda var1+1
sbc #0
sta var2+1
fuelex lda var5
sta (var2),y ;1
inc var5
lda var5
iny
sta (var2),y ;2
inc var5
lda var5
iny
sta (var2),y ;3
clc
lda var2
adc #41
sta var2
lda var2+1
adc #0
sta var2+1
dey
inc var5
lda var5
sta (var2),y ;4
dey
inc var5
lda var5
sta (var2),y ;5
dey
inc var5
lda var5
sta (var2),y ;6
clc
lda var2
adc #40
sta var2
lda var2+1
adc #0
sta var2+1
inc var5
lda var5
sta (var2),y ;7
inc var5
lda var5
iny
sta (var2),y ;8
inc var5
lda var5
iny
sta (var2),y ;9
clc
lda var2
adc #40
sta var2
lda var2+1
adc #0
sta var2+1
inc var5
lda var5
sta (var2),y ;10
dey
inc var5
lda var5
sta (var2),y ;11
dey
inc var5
lda var5
sta (var2),y ;12
tya
rts
; ------------------------------------------------------------------------------
kollitem ;Kollisionsroutine
;var8 unveränderter Bildschirmanfang
lda yschuss1 ;in Gr.0 -32 (sichtbarer Bereich ab 32 und /8
sec
sbc #32
clc
ror
clc
ror
clc
ror
sta yschuss1 ;y-Position in das x-Register schreiben
tax
dex ; und einen abziehen
lda xschuss1 ;x-Position -48 (sichtbarer Bereich)und /4
sec
sbc #48
clc
ror
clc
ror
tay ;in y geht die x-Position
sec
mva var1 var2 ;holen der Bildschirmadresse -> var2
mva var1+1 var2+1
clc
@ lda var2 ;jetzt die y-Position auf die richtige Höhe stellen
adc #40
sta var2
lda var2+1
adc #0
sta var2+1
dex
bpl @- ;die y-Position steht in x - Addition von x Zeilen
@ dey ;die korrekte x-Position einstellen
lda (var2),y ;linken Rand checken
sta var8
iny
iny
lda (var2),y ;rechten Rand checken
sta var9
dey
dey
#if .byte var8=#0 .and .byte var9>#0 ;Position nach rechts anpassen
iny
#end
#if .byte var8>#0 .and .byte var9=#0 ;Position nach links anpassen
dey
#end
lda (var2),y ;2. Durchgang der Anpassung um letzte
sta var8 ;Fehler zu beseitigen
iny
iny
lda (var2),y
sta var9
dey
dey
#if .byte var8=#0 .and .byte var9>#0
iny
#end
#if .byte var8>#0 .and .byte var9=#0
dey
#end
lda (var2),y ;Korrektur der y-Position
sta var8 ;in var8 aktuelle BS-Position
sec
lda var2 ;eins drüber - bleibt wenn var2 zu tief
sbc #40
sta var2
lda var2+1
sbc #0
sta var2+1
lda (var2),y ;lade Bildschirminhalt eins drüber
sta var9 ;das geht in var9 rein
#if .byte var8>#0 .and .byte var9=#0 ;alte Position var2
clc ;wiederherstellen
lda var2
adc #40
sta var2
lda var2+1
adc #0
sta var2+1
#end
#if .byte var8=#0 .and .byte var9=#0 ;alte Position var2
clc ;eins runter
lda var2
adc #80
sta var2
lda var2+1
adc #0
sta var2+1
#end
lda (var2),y ;2. Durchgang der Anpassung um letzte
sta var8 ;Fehler zu beseitigen
sec
lda var2
sbc #40
sta var2
lda var2+1
sbc #0
sta var2+1
lda (var2),y
sta var9
#if .byte var8>#0 .and .byte var9=#0
clc
lda var2
adc #40
sta var2
lda var2+1
adc #0
sta var2+1
#end
#if .byte var8=#0 .and .byte var9=#0
clc
lda var2
adc #80
sta var2
lda var2+1
adc #0
sta var2+1
#end
;ab hier stimmt die Position des Items (meistens)
;in der Variable y für x-Position
;und in var2 für die y-Position
expl11
mva var2 tank1pos ;y-Position für Explosion1
mva var2+1 tank1pos+1
mva #68 var5
jsr fuelex
tay
iny
expl22
mva #80 var5
mva tank1pos var2
mva tank1pos+1 var2+1
mva #1 delay
jsr wartes
jsr fuelex
tay
iny
expl33
mva #92 var5
mva tank1pos var2
mva tank1pos+1 var2+1
mva #1 delay
jsr wartes
jsr fuelex
tay
iny
expl44
mva #104 var5
mva tank1pos var2
mva tank1pos+1 var2+1
mva #1 delay
jsr wartes
jsr fuelex
tay
iny
rts
; ------------------------------------------------------------------------------
text ldx #0
lda #52
jsr prte
inx
lda #45
jsr prte
inx
lda #54
jsr prte
inx
lda #31
jsr prte
inx
lda #52
jsr prte
inx
lda #49
jsr prte
inx
lda #0
jsr prte
inx
lda #54
jsr prte
inx
lda #50
jsr prte
inx
lda #0
jsr prte
inx
lda #51
jsr prte
inx
lda #47
jsr prte
inx
lda #50
jsr prte
inx
lda #42
jsr prte
inx
lda #50
jsr prte
inx
lda #53
jsr prte
inx
lda #0
jsr prte
inx
lda #55
jsr prte
inx
lda #34
jsr prte
inx
lda #32
jsr prte
inx
lda #34
jsr prte
inx
lda #34
jsr prte
inx
lda #0
jsr prte
inx
lda #51
jsr prte
inx
lda #45
jsr prte
inx
lda #54
jsr prte
inx
lda #45
jsr prte
inx
lda #52
jsr prte
inx
lda #0
jsr prte
inx
lda #51
jsr prte
inx
lda #52
jsr prte
inx
lda #50
jsr prte
inx
lda #44
jsr prte
inx
lda #45
jsr prte
inx
lda #47
jsr prte
inx
lda #48
jsr prte
inx
lda #0
jsr prte
ldx #0 ;Fuel
lda #46
jsr prte2
inx
lda #31
jsr prte2
inx
lda #45
jsr prte2
inx
lda #48
jsr prte2
ldx #10 ;Score
lda #53
jsr prte2
inx
lda #43
jsr prte2
inx
lda #50
jsr prte2
inx
lda #52
jsr prte2
inx
lda #45
jsr prte2
inx
lda #0
jsr prte2
inx
lda #160
jsr prte2
inx
lda #32
jsr prte2
inx
lda #32
jsr prte2
inx
lda #32
jsr prte2
ldx #23 ;Ships
lda #53
jsr prte2
inx
lda #47
jsr prte2
inx
lda #33
jsr prte2
inx
lda #51
jsr prte2
inx
lda #53
jsr prte2
inx
lda #0
jsr prte2
inx
lda #28
jsr prte2
inx
lda #29
jsr prte2
inx
lda #0
jsr prte2
inx
lda #28
jsr prte2
inx
lda #29
jsr prte2
inx
lda #0
jsr prte2
inx
lda #28
jsr prte2
inx
lda #29
jsr prte2
ldx #0
fuellauf
clc
lda fuelzaehleritem
@ jsr prte3
inx
cpx #36
bne @-
rts
prte sta 30923,x
sta 32423,x
rts
prte2 sta 31003,x
sta 32503,x
rts
prte3 sta 31043,x
sta 32543,x
rts
; ------------------------------------------------------------------------------
run main
lands:
;@com.wudsn.ide.asm.mainsourcefile=test.asm
; Aufbau der letzten Reihe:
; Boarder1 Boarder2 Rand1(gelb) Mitte(Leerraum) Rand2(gelb) Boarder3 Boarder4 Item(z.B. Öltank - Charakter 56)
; Beispiel: 3,2,4,1,5,22,6,4,2,1,1,56,11
; 3x BoarderArt 2 printen / 4x BoarderArt 1 printen / 1x RandArt 1 printen / 22 Leerzeichen printen
; 1x RandArt 6 printen, 4x BoarderArt 2 printen, 1x BoarderArt 1 printen, Öltank (56) an Stelle 11 printen
; Die Routine "letztereihe" verarbeitet dies kontinuierlich nach jedem Feinscroll/Grobscroll
lands .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,2,4,2,10,22,11,4,2,1,2,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0 ;22
.byte 6,1,5,2,10,16,11,4,1,1,1,56,9
.byte 6,1,5,1,10,13,11,2,2,6,1,0,0
.byte 6,1,5,1,10,13,11,2,1,6,1,0,0
.byte 6,1,5,1,10,13,11,2,1,6,1,0,0
.byte 6,1,5,1,10,13,11,2,1,6,1,0,0
.byte 6,1,5,1,10,13,11,2,1,6,1,0,0
.byte 6,1,5,1,10,13,11,2,1,6,1,0,0
.byte 6,1,5,1,10,13,11,2,1,6,1,0,0
.byte 6,1,5,1,10,13,11,2,1,6,1,0,0
.byte 12,1,3,2,7,9,11,2,1,6,1,56,14
.byte 13,1,3,1,7,8,11,2,1,6,1,0,0
.byte 13,1,4,1,7,7,11,2,1,6,1,0,0
.byte 13,1,5,1,10,6,11,2,1,6,1,0,0
.byte 13,1,4,1,8,7,11,2,1,6,1,0,0
.byte 17,1,0,8,0,7,11,2,1,6,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0 ;22
.byte 6,1,5,2,10,16,11,4,1,1,1,56,9
.byte 6,1,5,1,10,13,11,2,2,6,1,0,0
.byte 6,1,5,1,10,13,11,2,1,6,1,0,0
.byte 6,1,5,1,10,13,11,2,1,6,1,0,0
.byte 6,1,5,1,10,13,11,2,1,6,1,0,0
.byte 6,1,5,1,10,13,11,2,1,6,1,0,0
.byte 6,1,5,1,10,13,11,2,1,6,1,0,0
.byte 6,1,5,1,10,13,11,2,1,6,1,0,0
.byte 6,1,5,1,10,13,11,2,1,6,1,0,0
.byte 12,1,3,2,7,9,11,2,1,6,1,56,14
.byte 13,1,3,1,7,8,11,2,1,6,1,0,0
.byte 13,1,4,1,7,7,11,2,1,6,1,0,0
.byte 13,1,5,1,10,6,11,2,1,6,1,0,0
.byte 13,1,4,1,8,7,11,2,1,6,1,0,0
.byte 17,1,0,8,0,7,11,2,1,6,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0 ;22
.byte 6,1,5,2,10,16,11,4,1,1,1,56,9
.byte 6,1,5,1,10,13,11,2,2,6,1,0,0
.byte 6,1,5,1,10,13,11,2,1,6,1,0,0
.byte 6,1,5,1,10,13,11,2,1,6,1,0,0
.byte 6,1,5,1,10,13,11,2,1,6,1,0,0
.byte 6,1,5,1,10,13,11,2,1,6,1,0,0
.byte 6,1,5,1,10,13,11,2,1,6,1,0,0
.byte 6,1,5,1,10,13,11,2,1,6,1,0,0
.byte 6,1,5,1,10,13,11,2,1,6,1,0,0
.byte 12,1,3,2,7,9,11,2,1,6,1,56,14
.byte 13,1,3,1,7,8,11,2,1,6,1,0,0
.byte 13,1,4,1,7,7,11,2,1,6,1,0,0
.byte 13,1,5,1,10,6,11,2,1,6,1,0,0
.byte 13,1,4,1,8,7,11,2,1,6,1,0,0
.byte 17,1,0,8,0,7,11,2,1,6,1,0,0
.byte 1,1,4,1,10,22,11,4,1,1,1,0,0
character:
;@com.wudsn.ide.asm.mainsourcefile=test2.asm
chr .byte 0,0,0,0,0,0,0,0
.byte 255,255,255,255,255,255,255,255 ;1 Color 2 (grün - alternativ)
.byte 170,255,255,255,255,255,255,255
.byte 255,255,255,255,255,255,255,170
.byte 128,224,248,248,248,248,224,128
.byte 2,11,47,47,47,47,11,2
.byte 170,255,255,255,255,255,255,170 ;6
.byte 128,224,224,248,248,248,254,254
.byte 254,254,248,248,248,224,224,128
.byte 254,254,248,248,248,224,224,170
.byte 128,128,128,128,128,128,128,128
.byte 2,2,2,2,2,2,2,2
.byte 254,254,254,254,254,254,254,254 ;12
.byte 191,191,191,191,191,191,191,191
.byte 0,0,0,0,0,0,0,0
.byte $e0,$e0,$ee,$ee,$ee,$ee,$e0,$e0
.byte $ee,$ee,$ee,$ee,$ee,$ee,$ee,$ee
.byte $0e,$0e,$ee,$ee,$ee,$ee,$0e,$0e
.byte $e0,$e0,$e0,$e0,$e0,$e0,$e0,$e0
.byte $0e,$0e,$0e,$0e,$0e,$0e,$0e,$0e
.byte $0,$0,$0,$0,$ee,$ee,$ee,$ee
.byte $ee,$ee,$ee,$ee,0,0,0,0
.byte $e0,$e0,$e0,$e0,$ee,$ee,$ee,$ee
.byte 0,0,255,255,255,255,0,0 ;Fuel lauf - 123
.byte 0,0,63,63,63,63,0,0 ;F
.byte 0,0,15,15,15,15,0,0 ;U - 25
.byte 0,0,3,3,3,3,0,0 ;U
.byte 0,0,0,0,0,0,0,0 ;E - 27
.byte 1,4,4,21,85,81,64,64 ;28 -> Schiff klein
.byte 64,16,16,84,85,69,1,1 ;29 -> Schiff klein
.byte 0,0,0,0,0,0,$f0,$f0 ;L
.byte 136,136,136,136,136,136,136,168 ;31 -> U
.byte 32,136,136,136,168,136,136,32 ;32 -> 0
.byte 32,32,32,32,32,32,32,32
.byte 168,8,8,168,168,128,128,168 ;34 -> 2
.byte 170,2,2,170,170,2,2,170 ;33 -> 5
.byte 128,136,136,170,170,8,8,8 ;36 -> 4
.byte 170,128,128,170,170,2,2,170
.byte 128,128,128,170,130,130,130,170 ;38 -> 6
.byte 168,8,8,42,42,8,8,8
.byte 170,130,130,170,170,130,130,170 ;40 -> 8
.byte 170,130,130,170,170,2,2,2 ;41 -> 9
.byte 160,136,136,160,160,136,136,160 ;42 -> B
.byte 40,128,128,128,128,128,128,40 ;43 -> C
.byte 160,136,136,136,136,136,136,160 ;44 -> D
.byte 168,128,128,168,168,128,128,168 ;45 -> E
.byte 168,128,128,168,168,128,128,128 ;46 -> F
.byte 136,136,136,168,168,136,136,136 ;47 -> H
.byte 128,128,128,128,128,128,128,170 ;48 -> L
.byte 130,130,162,162,138,138,138,130 ;49 -> N
.byte 32,136,136,136,136,136,136,32 ;50 -> O
.byte 160,136,136,168,160,128,128,128 ;51 -> P
.byte 160,136,136,168,160,136,136,136 ;52 -> R
.byte 40,128,128,168,168,8,8,160 ;53 -> S
.byte 168,168,32,32,32,32,32,32 ;54 -> T
.byte 0,0,8,32,32,32,32,8 ;55 -> c
tank .byte 0,0,0,0,15,15,53,53 ;56 -> Fuel Tank
.byte 0,0,255,255,255,255,185,185
.byte 0,0,192,192,252,252,111,111
.byte 239,239,111,111,239,239,107,107
.byte 185,185,185,185,185,185,169,169
.byte 55,55,53,53,55,55,55,55
.byte 15,15,0,0,0,0,2,2
.byte 255,255,136,136,136,136,170,170
.byte 252,252,128,128,128,128,160,160
.byte 32,32,168,168,8,8,42,42
.byte 8,8,170,170,8,8,42,42
.byte 2,2,10,10,8,8,42,42 ;67
expl1 .byte 0,0,0,32,32,8,5,1 ;68
.byte 0,0,0,2,24,85,154,102
.byte 0,0,64,64,0,0,66,72
.byte 80,144,160,84,152,100,100,170
.byte 101,153,153,86,102,106,153,153
.byte 5,9,134,22,25,41,22,150
.byte 166,25,25,41,86,6,5,9
.byte 154,102,102,149,153,90,101,166
.byte 89,84,100,164,104,80,144,144
.byte 64,6,8,0,0,0,0,0
.byte 150,153,89,20,2,0,0,0
.byte 17,1,0,2,8,0,0,0 ;79
expl2 .byte 0,0,0,0,0,0,0,0 ;80
.byte 0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0
.byte 4,16,128,128,64,64,64,160
.byte 20,90,89,165,150,90,105,101
.byte 8,8,1,1,1,2,6,5
.byte 1,2,2,1,1,8,8,32
.byte 149,153,170,102,85,105,24,20
.byte 96,64,128,144,16,0,0,0
.byte 0,0,0,0,0,0,0,0
.byte 8,2,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0 ;91
expl3 .byte 0,0,0,0,0,0,0,0 ;92
.byte 0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0
.byte 0,0,0,2,24,89,102,150
.byte 0,0,0,0,2,0,0,0
.byte 0,0,2,0,0,0,0,0
.byte 169,89,90,36,0,0,0,0
.byte 0,0,0,128,0,0,0,0
.byte 0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0 ;103
expl4 .byte 0,0,0,0,0,0,0,0 ;104
.byte 0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0
.byte 15,15,0,0,0,0,2,2
.byte 255,255,136,136,136,136,170,170
.byte 252,252,128,128,128,128,160,160
.byte 32,32,168,168,8,8,42,42
.byte 8,8,170,170,8,8,42,42
.byte 2,2,10,10,8,8,42,42
.byte $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f ;F - 132
.byte $f0,$f0,0,0,$f0,0,0,0 ;F
.byte $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f ;U - 134
.byte $0f,$0f,$0f,$0f,$0f,$0f,$ff,$ff ;U
.byte $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f ;E - 136
.byte $f0,$f0,0,0,$f0,0,$f0,$f0 ;E
.byte $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f ;L - 138
.byte 0,0,0,0,0,0,$f0,$f0 ;L
.byte $44,$44,$44,$44,$40,$40,$40,$40
.byte $04,$04,$04,$04,$44,$44,$44,$44
.byte $44,$44,$44,$44,$04,$04,$04,$04
.byte $30,$30,$33,$33,$33,$33,$30,$30 ;143
.byte $33,$33,$33,$33,$33,$33,$33,$33
.byte $03,$03,$33,$33,$33,$33,$03,$03
.byte $30,$30,$30,$30,$30,$30,$30,$30
.byte $03,$03,$03,$03,$03,$03,$03,$03
.byte $0,$0,$0,$0,$33,$33,$33,$33
.byte $33,$33,$33,$33,0,0,0,0
.byte $30,$30,$30,$30,$33,$33,$33,$33
.byte $33,$33,$33,$33,$30,$30,$30,$30
.byte $03,$03,$03,$03,$33,$33,$33,$33
.byte $33,$33,$33,$33,$03,$03,$03,$03
.byte $20,$20,$22,$22,$22,$22,$20,$20 ;154
.byte $22,$22,$22,$22,$22,$22,$22,$22
.byte $02,$02,$22,$22,$22,$22,$02,$02
.byte $20,$20,$20,$20,$20,$20,$20,$20
.byte $02,$02,$02,$02,$02,$02,$02,$02
.byte $0,$0,$0,$0,$22,$22,$22,$22
.byte $22,$22,$22,$22,0,0,0,0
.byte $20,$20,$20,$20,$22,$22,$22,$22
.byte $22,$22,$22,$22,$20,$20,$20,$20
.byte $02,$02,$02,$02,$22,$22,$22,$22
.byte $22,$22,$22,$22,$02,$02,$02,$02
.byte $10,$10,$11,$11,$11,$11,$10,$10 ;165
.byte $11,$11,$11,$11,$11,$11,$11,$11
.byte $01,$01,$11,$11,$11,$11,$01,$01
.byte $10,$10,$10,$10,$10,$10,$10,$10
.byte $01,$01,$01,$01,$01,$01,$01,$01
.byte $0,$0,$0,$0,$11,$11,$11,$11
.byte $11,$11,$11,$11,0,0,0,0
.byte $10,$10,$10,$10,$11,$11,$11,$11
.byte $11,$11,$11,$11,$10,$10,$10,$10
.byte $01,$01,$01,$01,$11,$11,$11,$11
.byte $11,$11,$11,$11,$01,$01,$01,$01
.byte $10,$10,$11,$11,$11,$11,$10,$10 ;176
.byte $11,$11,$11,$11,$11,$11,$11,$11
.byte $01,$01,$11,$11,$11,$11,$01,$01
.byte $10,$10,$10,$10,$10,$10,$10,$10
;184 Fuel-Tank
;.byte 0,0,0,0,15,15,53,53
;.byte 0,0,255,255,255,255,185,185
;.byte 0,0,192,192,252,252,111,111
;.byte 239,239,111,111,239,239,107,107
;.byte 185,185,185,185,185,185,169,169
;.byte 55,55,53,53,55,55,55,55 ;190
;.byte 15,15,0,0,0,0,2,2 ;191
;.byte 255,255,136,136,136,136,170,170 ;192
;.byte 252,252,128,128,128,128,160,160
;.byte 32,32,168,168,8,8,42,42
;.byte 8,8,170,170,8,8,42,42
;.byte 2,2,10,10,8,8,42,42
header:
var1 = $a0
var2 = $a2
var3 = $a4
var4 = $a6
var5 = $a8
var6 = $b2
var7 = $b4
lms1 = $b6
lms2 = $b8
lmslo = $a0
lmshi = $a2
delay = $b0
play1 = $92
play2 = $94
play3 = $96
play4 = $98
miss1 = $c0
miss2 = $c2
miss3 = $c4
miss4 = $c6
rechts = $c8
links = $c9
xposp1 = $ca
yposp1 = $cb
joyst1 = $cc
kollp0 = $cd
xposm1 = $ce
yposm1 = $cf
xposm2 = $d0
yposm2 = $d1
xposm3 = $dc
yposm3 = $dd
kollm1 = $d2
kollm2 = $d3
feuer1 = $d4
feuer2 = $d5
yposm1hilf = $d6
feuer3 = $d7
feuer4 = $d8
yposm2hilf = $d9
feuer5 = $da
feuer6 = $db
blink = $de
blink2 = $df
ysonder = $e0
xschuss1 = $e1
yschuss1 = $e2
xschuss2 = $e4
yschuss2 = $e5
var8 = $e7
var9 = $e8
kollges = $f0
explosion1 = $f1
itemex = $f2
tank1exp = $f4
tank1pos = $f6
tank1x = $f8
tank1y = $fa
exp1 = $1900
exp2 = $1902
exp3 = $1904
exp4 = $1906
fuelzaehler = $1908
fuelzaehleritem = $1909
hardware:
LINZBS = $0000
CASINI = $0002
RAMLO = $0004
TRAMSZ = $0006
TSTDAT = $0007
WARMST = $0008
BOOT? = $0009
DOSVEC = $000a
DOSINI = $000c
APPMHI = $000e
POKMSK = $0010
BRKKEY = $0011
RTCLOK = $0012
BUFADR = $0015
ICCOMT = $0017
DSKFMS = $0018
DSKUTL = $001a
PTIMOT = $001c
PBPNT = $001d
PBUFSZ = $001e
PTEMP = $001f
ICHIDZ = $0020
ICDNOZ = $0021
ICCOMZ = $0022
ICSTAZ = $0023
ICBALZ = $0024
ICPTLZ = $0026
ICBLLZ = $0028
ICAX1Z = $002a
ICAX2Z = $002b
ICAX3Z = $002c
ICAX4Z = $002c
ICAX5Z = $002e
ICAX6Z = $002f
STATUS = $0030
CHKSUM = $0031
BUFRLO = $0032
BUFRHI = $0033
BFENLO = $0034
BFENHI = $0035
CRETRY = $0036
DRETRY = $0037
BUFRFL = $0038
RECVDN = $0039
XMTDON = $003a
CHKSNT = $003b
NOCKSM = $003c
BPTR = $003d
FTYPE = $003e
FEOF = $003f
FREQ = $0040
SOUNDR = $0041
CRITIC = $0042
FMZSPG = $0043
ZDRVA = $0045
ZSBA = $0047
ERRNO = $0049
CKEY = $004a
CASSBT = $004b
DSTAT = $004c
ATRACT = $004d
DRKMSK = $004e
COLRSH = $004f
TMPCHR = $0050
HOLD1 = $0051
LMARGN = $0052
RMARGN = $0053
ROWCRS = $0054
COLCRS = $0055
DINDEX = $0057
SAVMSC = $0058
OLDROW = $005a
OLDCOL = $005b
OLDCHR = $005d
OLDADR = $005e
NEWROW = $0060
NEWCOL = $0061
LOGCOL = $0063
ADRESS = $0064
MLTTMP = $0066
SAVADR = $0068
RAMTOP = $006a
BUFCNT = $006b
BUFSTR = $006c
BITMSK = $006e
SHFAMT = $006f
ROWAC = $0070
COLAC = $0072
ENDPT = $0074
DELTAR = $0076
DELTAC = $0077
ROWINC = $0079
COLINC = $007a
SWPFLG = $007b
HOLDCH = $007c
INSDAT = $007d
COUNTR = $007e
; hardware shadow registers
VDSLST = $0200
VPRCED = $0202
VINTER = $0204
VBREAK = $0206
VKEYBD = $0208
VSERIN = $020a
VSEROR = $020c
VSEROC = $020e
VTIMR1 = $0210
VTIMR2 = $0212
VTIMR4 = $0214
VIMIRQ = $0216
CDTMV1 = $0218
CDTMV2 = $021a
CDTMV3 = $021c
CDTMV4 = $021e
CDTMV5 = $0220
VVBLKI = $0222
VVBLKD = $0224
CDTMA1 = $0226
CDTMA2 = $0228
CDTMF3 = $022a
SRTIMR = $022b
CDTMF4 = $022c
INTEMP = $022d
CDTMF5 = $022e
SDMCTL = $022f
SDLSTL = $0230
SSKCTL = $0232
SPARE = $0233
LPENH = $0234
LPENV = $0235
BRKKY = $0236
CDEVIC = $023a
CCOMND = $023b
CAUX1 = $023c
CAUX2 = $023d
TEMP = $023e
ERRFLG = $023f
DFLAGS = $0240
DBSECT = $0241
BOOTAD = $0242
COLDST = $0244
DSKTIM = $0246
LINBUF = $0247
GPRIOR = $026f
PADDL0 = $0270
PADDL1 = $0271
PADDL2 = $0272
PADDL3 = $0273
PADDL4 = $0274
PADDL5 = $0275
PADDL6 = $0276
PADDL7 = $0277
STICK0 = $0278
STICK1 = $0279
STICK2 = $027a
STICK3 = $027b
PTRIG0 = $027c
PTRIG1 = $027d
PTRIG2 = $027e
PTRIG3 = $027f
PTRIG4 = $0280
PTRIG5 = $0281
PTRIG6 = $0282
PTRIG7 = $0283
STRIG0 = $0284
STRIG1 = $0285
STRIG2 = $0286
STRIG3 = $0287
CSTAT = $0288
WMODE = $0289
BLIM = $028a
TXTROW = $0290
TXTCOL = $0291
TINDEX = $0293
TXTMSC = $0294
TXTOLD = $0296
TMPX1 = $029c
HOLD3 = $029d
SUBTMP = $029e
HOLD2 = $029f
DMASK = $02a0
TMPLBT = $02a1
ESCFLG = $02a2
TABMAP = $02a3
LOGMAP = $02b2
INVFLG = $02b6
FILFLG = $02b7
TMPROW = $02b8
TMPCOL = $02b9
SCRFLG = $02bb
HOLD4 = $02bc
HOLD5 = $02bd
SHFLOK = $02be
BOTSCR = $02bf
PCOLR0 = $02c0
PCOLR1 = $02c1
PCOLR2 = $02c2
PCOLR3 = $02c3
COLOR0 = $02c4
COLOR1 = $02c5
COLOR2 = $02c6
COLOR3 = $02c7
COLOR4 = $02c8
; IO space
RUNAD = $02e0
INITAD = $02e2
RAMSIZ = $02e4
MEMTOP = $02e5
MEMLO = $02e7
DVSTAT = $02ea
CBAUDL = $02ee
CBAUDH = $02ef
CRSINH = $02f0
KEYDEL = $02f1
CH1 = $02f2
CHACT = $02f3
CHBAS = $02f4
CHAR = $02fa
ATACHR = $02fb
CH = $02fc
FILDAT = $02fd
DSPFLG = $02fe
SSFLAG = $02ff
DDEVIC = $0300
DUNIT = $0301
DCOMND = $0302
DSTATS = $0303
DBUFLO = $0304
DBUFHI = $0305
DTIMLO = $0306
DUNUSE = $0307
DBYTLO = $0308
DBYTHI = $0309
DAUX1 = $030a
DAUX2 = $030b
TIMER1 = $030c
ADDCOR = $030e
CASFLG = $030f
TIMER2 = $0310
TEMP1 = $0312
TEMP2 = $0314
TEMP3 = $0315
SAVIO = $0316
TIMFLG = $0317
STACKP = $0318
TSTAT = $0319
HATABS = $031a
IOCB0 = $0340
IOCB1 = $0350
IOCB2 = $0360
IOCB3 = $0370
IOCB4 = $0380
IOCB5 = $0390
IOCB6 = $03a0
IOCB7 = $03b0
PRNBUF = $03c0
CASBUF = $03fd
; GTIA write locations
HPOSP0 = $d000
HPOSP1 = $d001
HPOSP2 = $d002
HPOSP3 = $d003
HPOSM0 = $d004
HPOSM1 = $d005
HPOSM2 = $d006
HPOSM3 = $d007
SIZEP0 = $d008
SIZEP1 = $d009
SIZEP2 = $d00a
SIZEP3 = $d00b
SIZEM = $d00c
GRAFP0 = $d00d
GRAFP1 = $d00e
GRAFP2 = $d00f
GRAFP3 = $d010
GRAFM = $d011
COLPM0 = $d012
COLPM1 = $d013
COLPM2 = $d014
COLPM3 = $d015
COLPF0 = $d016
COLPF1 = $d017
COLPF2 = $d018
COLPF3 = $d019
COLBK = $d01a
PRIOR = $d01b
VDELAY = $d01c
GRACTL = $d01d
HITCLR = $d01e
CONSOL = $d01f
; GTIA read locations
M0PF = $d000
M1PF = $d001
M2PF = $d002
M3PF = $d003
P0PF = $d004
P1PF = $d005
P2PF = $d006
P3PF = $d007
M0PL = $d008
M1PL = $d009
M2PL = $d00a
M3PL = $d00b
P0PL = $d00c
P1PL = $d00d
P2PL = $d00e
P3PL = $d00f
TRIG0 = $d010
TRIG1 = $d011
TRIG2 = $d012
TRIG3 = $d013
PAL = $d014
; POKEY write locations
AUDF1 = $d200
AUDC1 = $d201
AUDF2 = $d202
AUDC2 = $d203
AUDF3 = $d204
AUDC3 = $d205
AUDF4 = $d206
AUDC4 = $d207
AUDCTL = $d208
STIMER = $d209
SKREST = $d20a
POTGO = $d20b
SEROUT = $d20d
IRQEN = $d20e
SKCTL = $d20f
; POKEY read locations
POT0 = $d200
POT1 = $d201
POT2 = $d202
POT3 = $d203
POT4 = $d204
POT5 = $d205
POT6 = $d206
POT7 = $d207
ALLPOT = $d208
KBCODE = $d209
RANDOM = $d20a
SERIN = $d20d
IRQST = $d20e
SKSTAT = $d20f
; PIA
PORTA = $d300
PORTB = $d301
PACTL = $d302
PBCTL = $d303
; ANTIC write locations
DMACTL = $d400
CHACTL = $d401
DLISTL = $d402
DLISTH = $d403
HSCROL = $d404
VSCROL = $d405
PMBASE = $d407
CHBASE = $d409
WSYNC = $d40a
NMIEN = $d40e
NMIRES = $d40f
; ANTIC read locations
VCOUNT = $d40b
PENH = $d40c
PENV = $d40d
NMIST = $d40f
NMIEN_DLI = $80
NMIEN_VBI = $40
; vector tables
EDITRV = $e400
SCRENV = $e410
KEYBDV = $e420
PRINTV = $e430
CASETV = $e440
DISKIV = $e450
DSKINV = $e453
CIOV = $e456
SIOV = $e459
SETVBV = $e45c
SYSVBV = $e45f
XITVBV = $e462
SIOINV = $e465
SENDEV = $e468
INTINV = $e46b
CIOINV = $e46e
BLKBDV = $e471
WARMSV = $e474
COLDSV = $e477
RBLOKV = $e47a
CSOPIV = $e47d
Gruß Peter
Hallo Peter,
ich habe nur ein paar kleine Dinge geändert und auch 2, 3 Hinweise hinzugefügt. Ich denke der Unterschied ist schnell zu sehen und Du kannst das selbst nach Deinem Gutdünken ausweiten. Aber das Teilen und in Prozeduren packen hilft ungemein bei größeren Projekten. Wie man ein Label in einer anderen Prozedur ansprechen kann, sieht man bei einigen jsr fuel.fuelex aufrufen.
Bei "go lucky" und "runfast" habe ich da auch ordentlich Code in halbwegs übersichtliche Dateien packen können. So konnte ich auch viel Code von "go lucky" direkt bei "runfast" wieder verwenden. Das hat die Entwicklung enorm beschleunigt.
Viel Spaß beim weitercoden 😉 Ich hoffe, Dir das nun ein wenig leichter gemacht zu haben. Ralf
PS: Die erste Zeile in den ausgelagerten Dateien sorgt dafür, dass man dort direkt das gesamte Programm assemblieren kann.
PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo
Guten Morgen Ralf, vielen Dank für deine Mühe und Arbeit. Größere Abschnitte sinnvoll auszulagern macht auf jeden Fall Sinn - also auch der VBI. An der DList muss ich noch ein wenig rumschrauben... wahrscheinlich kommt da auch noch ein Interrupt rein.
Der VBI ist zu lang, da muss ich noch kürzen... was unheimlich aufwendig als Code geworden ist, ist das Blinken des Raumschiffes. Das muss viel einfacher gehen. Auch mit den Schüssen bin ich nicht so ganz zufrieden - ich wollte es so programmieren, das die Schüsse nur abwechselnd ausgelöst werden können, vielleicht muss ich da noch einen anderen Weg gehen. Das Printen der letzten Reihe (ist nicht im VBI) ist zu aufwendig, das muss ich auch ändern, ich habe da auch schon eine gute Idee. Ein großer Knackpunkt ist auch die genaue Kollisionserkennung... da habe ich richtig viel Code reingesteckt und es läuft immer noch nicht 100% ig richtig. Das werde ich auch komplett umbauen. Eigentlich geht es da ja hauptsächlich um die korrekte x-Position des getroffenen Items - sowohl die x als auch die y-Position habe ich beim printen - vielleicht speicher ich das einfach zwischen und greife dann bei der Kollision darauf zurück und muss nur die y-Position ändern - die habe ich ja aber zum Zeitpunkt der Kollision........ Jetzt baue ich aber zunächst die Landschaft weiter aus und die anderen Items, damit ich die Landschaft befüllen kann - dann kümmere ich mich um die Codeverbesserungen und Fehlerbereinigungen. Ideen und Codefehler-/Optimierungsvorschläge sind auf jeden Fall gerne gesehen!
Für mich dient dieses Projekt in erster Linie, um Spaß beim programmieren zu haben und um zu lernen... wenn ich meine Anfänge im August 2021 ("Hallo Welt") mit dem Fortschritt jetzt vergleiche, dann bin ich mehr als zufrieden! LG Peter
Prodehl schrieb: ... wenn ich meine Anfänge im August 2021 ("Hallo Welt") mit dem Fortschritt jetzt vergleiche, dann bin ich mehr als zufrieden!
Das kannst Du auch sein! Respekt. 🙂 Wenn ich überlege wie oft ich mit Assembler schon angefangen habe und dann hängen geblieben bin... 🙄
Sleeπ
Hallo!
Ich nutze in meinem Programm viele Subroutinen und würde Deine "Blinkroutine" entsprechend so ändern:
blinklinks ldy yposm3
lda #0
sta (miss1),y
mva hposp0 xposm3
lda yposp1
clc
adc #6
tay
lda #48
sta (miss1),y
mva xposp1 p2pf
mva xposp1 xposm3
sty yposm3
rts
blinkrechts ldy yposm3
lda #0
sta (miss1),y
lda yposp1
clc
adc #6
tay
lda #192
sta (miss1),y
lda xposp1
clc
adc #14
sta p3pf
mva xposp1 xposm3
sty yposm3
rts
write
lda xposp1 ;Blinkabschnitt
sta hposp0
adc #2
sta hposp3
#if .byte blink<#64 ;Blink links
jsr blinklinks
#end
#if .byte blink>#63 .and .byte blink<#128 ;Blink rechts
jsr blinkrechts
#end
#if .byte blink>#127 .and .byte blink<#192 ;Blink links
jsr blinklinks
#end
#if .byte blink>#191 .and .byte blink<#255 ;Blink rechts
jsr blinkrechts
#end
Bei mir funktioniert es.
Ist jetzt nur ein Beispiel, wie man den Code kürzen kann.
Grüße Janko
Meine Projekte findest Du hier...
Hallöle... das baue ich später gleich mal ein und probiere es aus!! Supi! LG
... ich habe beide Änderungen eingebaut und noch den kleinen zusätzlichen Fehler beseitigt, der mich schon die ganze Zeit nervt - nämlich daß durch den Blinker immer mal wieder ein paar Bits auf dem Screen stehenbleiben - bei der Abfrage statt > und < einfach ein >= und <= ersetzt und schon ist es weg - logisch. Ansonsten finde ich die neue Blinkerroutine schlanker und strukturierter... supi. Auch den VBI auszulagern macht Sinn. Der VBI muss aber noch ein wenig schlanker werden, ein paar Sachen sollen da ja noch rein und die Sounds fehlen ja auch noch komplett. Außerdem muss ich den Aufbau der letzten Reihe noch optimieren..das hatte ich schon vorgestern deutlich besser und schlanker umgesetzt, aber nachts um 1:30 war dann mit meiner Konzentration Schluss und den einen Fehler habe ich einfach nicht wegbekommen und es wurde immer schlimmer, so daß ich auf meine alte Routine zurückgegangen bin und diese dann erweitert habe. Auch muss ich mir Gedanken machen, wie ich das so gestalte, daß ich die letzte Reihe einfacher konstruieren kann... so ist es ganz schön mühsam... vielleicht baue ich mit extra dafür ein kleines Programm welches übersichtlicher die Landschaft bauen läßt...
... gerade noch einen kleinen Bug in der Routine der letzten Reihe fixiert... da war ein inc var5 zu viel... jetzt läuft es ganz ohne Fehler 😎
Ich habe die komplette Joystickabfrage und Bewegung des Players ausserhalb des VBI. Als erstes wird der Joystick abgefragt, dann die neue Position berechnet. Nun warte ich auf einen VSync (also dass das Bild gerade nicht aufgebaut wird) und positioniere meinen Player.
; ############################################################################
; # VSync
; #
.proc WaitVSync
lda VCOUNT
cmp #$68
bcc @+1
@ lda VCOUNT
cmp #$68
bcs @-
@ lda VCOUNT
cmp #$68
bcc @-
rts
.end
Die Routine schaut, welche Bildschirmzeile gerade aufgebaut wird. Ist der Wert kleiner $68 warte ich auf darauf, dass dieser Wert überschritten wird. Ist der Wert bereits über $68, warte ich erst einmal, dass dieser kleiner $68 ist.
Der Wert $68 kommt daher, dass mein Spielfeld nicht bis nach ganz unten reicht und ich somit mehr Zeit für die Playerdarstellung habe.
Vielleicht kannst Du das irgendwie nutzen?
Meine Projekte findest Du hier...
Hallo Janko, das schaue ich mir mal später an.... das würde natürlich den VBI deutlich entlasten. Liebe Dank!!
Ich habe jetzt die anderen Items programmiert und dabei leider feststellen müssen, daß ich zu leichtfertig mit der Anzahl der Charakter umgegangen bin, denn plötzlich war b ei 128 Schluß... also ran ans Werk, optimieren und umprogrammieren. Danach ging es an die restlichen Items und danach habe ich die Landschaft weiter ausgebaut...
Nun werde ich die nächsten Tage und Wochen weiter an der Landschaft arbeiten, dann kommen noch Kollisionsabfragen und Aktionen auf die Kollisionen und weitere Items, die aktiv und animiert sind... danach Sound - ein noch riesiger Brocken! Das Projekt wächst und macht Spass...
Ein kleiner aktueller Stand anbei:
... ich war trotz wenig Zeit nicht untätig!
Bevor ich den Sound angehe, gibt es noch etliches an Code Bereinigung!
Der VBI muss schlanker und ich habe zunächst mit dem Blinker des Raumschiffes begonnen.
Für den Blinker hatte ich ursprünglich 2 Missiles benutzt und die im VBI aufwendig abwechselnd blinken lassen. Dadurch habe ich aber auch nur noch 2 Missiles für die Schüsse übrig.
Ich habe das jetzt umprogrammiert und nehme zum blinken einfach einen weiteren Player, der am Raumschiff das Blinken übernimmt. Dadurch kann ich noch eine weitere Farbe ins Raumschiff bringen.
Der ganze Code wird dadurch schon etwas schlanker. Anschließend habe ich fast den gesamten Blinkcode aus dem VBI ins Hauptprogramm gezogen und die ganzen zeitaufwendigen IF - Abfragen sind jetzt im Hauptcode.
Jetzt kann ich den Code für die Schüsse umbauen - damit war ich noch nie so richtig zufrieden - außerdem sollen jetzt alle 4 Missiles als Schüsse benutzbar werden - auch den Code versuche ich wenn es geht auszulagern....
Liebe Grüße
Peter
... die letzten Tage konnte ich endlich meinen Atari-Raum einrichten - noch ist es nicht fertig, aber ich habe schon mal meinen 130 XE aufgebaut, die Fujinet drangehängt, mit meinem Netzwerk verbunden und dann direkt mit meinem Mac das Programm retrun2phobos.xex gestartet... und es läuft. Das war der erste Test meines Programmes auf einem original Atari-Rechner.


Cool. Sowas übers Netzwerk zu machen hat schon was 😀 Gruß Wolfgang
Sehr praktisch - programmieren auf dem Äpfelchen und testen direkt auf originaler Hardware ohne die Dateien erst hin-und herzukopieren. 😎
Sleeπ
.... die letzten Tage habe ich wieder an der Explosion und speziell heute an den Schüssen rumgebastelt... Ziele sind folgende: 1. Die Explosion muss noch genauer werden - hier sind noch Fehler bei der genauen Erkennung der Position der Items und eigentlich sollen die Explosionen auch während des Scrolling fortwährend laufen und nicht direkt komplett, was ja immer einen kleinen Stopp bedeutet. 2. Ich habe das blinken umgebaut und überwiegend aus dem VBI rausgeholt - funktioniert ganz gut - und habe jetzt 4 Schüsse zur Verfügung. Diese sollen im Wechsel rechts und links laufen und auch durchaus gleichzeitig. Das ganze muss so gestaltet werden, daß auch hier der VBI entlastet wird, da ich ihn noch für Sound brauche.
zu 1: Das habe ich leider noch nicht hinbekommen. Die momentane Idee ist folgende: Ich brauche 12 Charakter für die Explosion und habe 4 Animationsphasen. Die lasse ich ständig laufen im Hintergrund und bei einem Treffer werden die 12 Charakter fürs Item mit den 12 Charaktern der Explosion überschrieben - das Scrolling geht dann automatisch weiter und ich muss mich nicht ums Timing kümmern. Da können dann auch mehrere Explosionen nebeneinander laufen - Problem ist dann nur der Start-/ und Endpunkt der Explosion.... dafür habe ich noch keine Lösung!
zu 2: Ich habe heute die Schüsse komplett umgebaut. Die Joystickabfrage (Strig0) und das Setzen der benötigten Parameter für den jeweiligen Schuss kann ich im Hauptprogramm machen - mache ich redundant im Feinscroll und an anderen Stellen. Aber die eigentliche Bewegung des Schusses geht quasi nur im VBI da sonst der Schuss viel zu langsam ist... und hier bekomme ich wieder ein Zeit- und Kapazitätsproblem im VBI. Ein Schuss kein Problem, 2 Schüsse geht auch noch ist aber tricky, 4 Schüsse unabhängig ... puh... da steigt mir der VBI aus. Da habe ich einfach zu viele Bedingungen und Abfragen.... das muss doch einfach und schlank gehen !!!!! Meine letzte Idee ist nun folgende: Alle 4 Schüsse laufen ständig unabhängig mit einer relativ schlanken Routine ständig im Hintergrund im VBI von oben nach unten durch - kommt dann der Impuls (durch Strig0) für einen Schuss, verändere ich einfach die x und y- Parameter für den jeweiligen Schuss und er wird sichtbar (x) und startet in Höhe Abschuss vom Raumschiff (y). Das will ich jetzt mal die Tage umsetzen...
Vielleicht hat ja jemand für beide Probleme auch die zündende und bessere Idee wie man es am besten macht, denn wenn ich mir die ganzen Spiele so anschaue, muss das doch eigentlich ganz easy sein! Grüße Peter
Hallo!
Ich habe so eine Routine für Missiles zwar noch nicht geschrieben, stelle es mir aber wie folgt vor:
missile .byte $00, $00, $00, $00 ; vier Schüsse
..
..
..
.proc Schuessebewegen
ldy $00
lp ldx missile,y ; Lade Y-Position Schuss 0-3
cpx #$00
bne mv ; Wenn ungleich 0 muss der Missile bewegt werden
nx iny ; Schussnr. hochzählen
cpy #$04 ; max. 4 sind vorhanden
bne lp ; Wenn der letzte Schuss noch nicht bearbeitet, zurück
rts ; Unterroutine für Schüsse beendet
mv tya ; y retten
pha ; Unterroutine um den Schuss einen Schritt zu bewegen
..
..
..
pla ; y zurück holen
tay
jmp nx ; nächsten Schuss bearbeiten
.end
Wenn nun im Hauptprogramm festgestellt wird, dass geschossen wurde, bereitet man einen freien Missile vor, indem man ihn an die richtige Position setzt und setzt sta missile,x auf den y-Wert des Schusses. Die Routine erkennt nun dass der Missile bewegt werden muss. Man kann im Hauptprogramm die Kollision abfragen und dann auswerten."missile" sollte auf 0 gesetzt werden, wenn der Schuss den untern Rand erreicht hat oder ein Treffer erfolgte.
Ich hoffe Du kannst meinen Gedanken folgen und es hilft Dir weiter.
Janko
Meine Projekte findest Du hier...
Hallo Janko und vielen Dank für deinen kreativen Lösungsansatz! So ähnlich wie du es schreibst, habe ich es auch jetzt vor! Allerdings möchte ich so wenig Abfragen und Bedingungen in die Missileroutine im VBI reinpacken wie möglich. Rein theoretisch sollte es ja zu 4 Schüssen gleichzeitig kommen können, daher muss der VBI das auch zeitlich abarbeiten können - sonst macht es keinen Sinn. Dann kann das aber auch ständig im Hintergrund laufen und ich mache es nur jeweils (durch x-Positionierung) sichtbar. Also alle 4 Missiles laufen ständig vom Bildschirmoberrand zum Unterrand - wenn der Unterrand erreicht wird, dann startet der Missile wieder von oben. Die X-Position wird auf 0 gesetzt - also sieht man die Missiles primär nicht. Die Joystickabfrage läuft im Hauptprogramm (das packe ich in die Feinscrollroutine, da ich hier noch Zeit habe und eh mit einer Warteschleife verzögern muss) - sobald der Feuerknopf gedrückt wurde kommt der entsprechende Werte in die y-Position und x-Position des jeweiligen Missile und er wird sichtbar. Läuft er nach ganz unten oder an den Boarderrand geht x auf Null und der Missile wird wieder unsichtbar - passiert eine Kollision mit einem Item startet die Explosionsroutine. Entsprechend läuft das mit den anderen drei Missiles....
... hier nun das erste Ergebnis:
Ich habe zunächst ein Missile umgesetzt. Die Routine im VBI sieht. nun extrem abgespeckt so aus:
Alles andere läuft im Hauptprogramm. Die Joystickabfrage für den Schuss und das Setzen der Parameter. Ich habe den Schuss zur Kontrolle noch sichtbar am linken Bildrand mitlaufen lassen und man sieht im Video sehr schön, daß der Schuss ständig läuft und wegen des schlanken Codes den VBI praktisch gar nicht belastet. Drückt man den Feuerknopf, wird die Position auf x und y verändert und der Schuss wird sichtbar bis der untere Rand erreicht ist - dann geht die x Position wieder auf den hier noch gerade sichtbaren Bereich am linken Rand. Beim finalen Spiel wandert der dann natürlich ganz raus. Es sind noch ein paar Fehler drin und die Kollisionsabfrage muss noch rein! Außerdem muss noch eine intelligente Steuerung der 4 Schüsse rein, die einmal abgefeuert ja bis nach unten oder bis zur Kollision durchlaufen müssen. Hier das kurze Video:#

Peter
Heute habe ich an den Schüssen gearbeitet und alle 4 Schüsse funktionieren jetzt gut. Der Hauptcode liegt im Hauptprogramm und der VBI ist schlank und wenig belastet. Leider habe ich schon das nächste massive Problem... Aber hier erstmal der Code vom VBI und vom Hauptprogramm:
;@com.wudsn.ide.asm.mainsourcefile=r2phobos.asm
;vertical blank interrupt fr Joystick / PM
.proc vbinter
pha
txa
pha
tya
pha
mva #0 atract ;Bildschirmschoner aus
clc ;Kollisionen abfragen
lda p0pf
cmp #1
bcc @+
mva #1 kollp0
@
clc ;Joystickabfragen Player1
lda stick0
cmp #15 ;keine Joystickaktion
bcs @+
cmp #14
bcs nachob
cmp #13
bcs nachun
cmp #11
bcs nachli
cmp #10
bcs nachliob
cmp #9
bcs nachliun
sec
cmp #7
bcs nachre
cmp #6
bcs nachreob
cmp #5
bcs nachreun
@ jmp write
nachre clc
lda xposp1
cmp #192
bcs @+
inc xposp1
@ jmp write
nachreun
clc
lda xposp1
cmp #192
bcs @+
inc xposp1
@ jmp nachun
nachreob
clc
lda xposp1
cmp #192
bcs @+
inc xposp1
@ jmp nachob
nachli sec
lda xposp1
cmp #49
bcc @+
dec xposp1
@ jmp write
nachliun
sec
lda xposp1
cmp #49
bcc @+
dec xposp1
@ jmp nachun
nachliob
sec
lda xposp1
cmp #49
bcc @+
dec xposp1
@ jmp nachob
nachob
dec yposp1
clc
ldy yposp1 ;verticale Startpos. Player 1 + füllen
ldx #0
@ lda pm1,x
sta (play1),y
iny
inx
cpx #14
bne @-
jmp write
nachun
inc yposp1
clc
ldy yposp1 ;verticale Startpos. Player 1 + füllen
ldx #0
@ lda pm1,x
sta (play1),y
iny
inx
cpx #14
bne @-
jmp write
clc
write sec
lda xposp1 ;x-Position der Player setzen
sta hposp0
sbc #0
sta hposp2
adc #2
sta hposp3
ldy yposp1 ;Player printen
clc
lda blink
tax
dey
mva #0 lms2
@ lda pm41,x
sta (play4),y
lda pm42,x
sta (play3),y
iny
inx
inc lms2
lda lms2
cmp #14
bne @-
;Schüsse laufen ständig
jsr schuesse
mva m0pf kollm1
mva m1pf kollm2
mva m2pf kollm3
mva m3pf kollm4
mva #1 hitclr
;-------------------------------------------------------------
pla
tay
pla
tax
pla
jmp xitvbv ;vb-interrupt wird über xitvbv beendet!!
.endp
org $2000
icl '../hardware.txt'
icl 'header.txt'
icl 'character.asm'
icl 'lands.asm'
.proc dlist
.by 112,112,112,100
.by 30,75
:21 .by 36
:5 .by 4
.by 65
.wo dlist
.endp
icl 'pmg_vars.asm'
.proc main
main1 mwa #dlist 560
mva #10 yposp1
mva #120 xposp1
mva #42 yposm1
mva #0 xposm1
mva #94 yposm2
mva #49 xposm2
mva #0 tank1x
mva #0 tank1y
mva #151 fuelzaehleritem
mva #0 fuelzaehler
jsr text
Start1 mva #>chr chbas ;HighByte Character Pointer auf $2000 setzen
mva #192 gprior ;GTIA Modus 3
mva #12 color3 ;Schriftfarbe
mva #220 color1 ;Gelb
mva #153 color0 ;Blau
;mva #52 color0 ;Rot
mva #180 color2 ; Grün
mva #0 color4 ;Hintergrundfarbe
lda #0 \ tax \ sta var3 \ sta var4 \ sta var6 \ sta var7 \ sta var6+1 \ sta feuer6
; Player vorbereiten und initialisieren
; Kollisionen: 4 = Grün 2 = Gelb
lda ramtop
sec
sbc #16
sta pmbase
clc
adc #3
sta miss1+1
sta miss2+1
sta miss3+1
sta miss4+1
adc #1
sta play1+1
adc #2
sta play3+1
adc #1
sta play4+1
lda #9
sta play4
lda #3
sta play3
mva #62 sdmctl
mva #56 pcolr0
mva #15 pcolr1
mva #119 pcolr2
mva #191 pcolr3
mva #1 gprior
mva #3 gractl
mva #1 sizep0
mva #1 sizep1
mva #1 sizep2
mva #0 sizem
mva #0 rechts
mva #2 hitclr
mva #48 blink
mva #40 p1pf
mva #8 hposm0
mva #8 hposm1
mva #8 hposm2
mva #8 hposm3
mva #1 yschuss1
mva #11 yschuss2
mva #22 yschuss3
mva #33 yschuss4
mva #1 schussi
main2 mva <lands var6
mva >lands var6+1
mva #0 kollp0
ldy #255 ;Speicher Player 1 leeren
lda #0
sta play1
@ sta (play1),y
sta (play4),y
sta (play3),y
dey
bpl @-
clc
ldy yposp1 ;verticale Startpos. Player 1 + füllen
ldx #0
@ lda pm1,x
sta (play1),y
iny
inx
cpx #14
bne @-
clc
ldy #0
ldx #0
ldx #>vbinter ;VB-Interrupt VektorHi
ldy #<vbinter ;VB-Interrupt VektorLo
lda #7 ;Deferred Mode mit lda #7 festlegen
jsr setvbv ;Vektor für die eigene Routine über setvbv eintragen
hauptprogramm
#if .byte yschuss1>#207 .or .byte kollm1=#4
ldy yschuss1
dey
lda #0
sta (miss1),y
iny
sta (miss1),y
mva #8 hposm0
mva #1 hitclr
#end
#if .byte yschuss2>#207 .or .byte kollm2=#4
ldy yschuss2
dey
lda #0
sta (miss1),y
iny
sta (miss1),y
mva #8 hposm1
mva #1 hitclr
#end
#if .byte yschuss3>#207 .or .byte kollm3=#4
dey
lda #0
sta (miss1),y
iny
sta (miss1),y
mva #8 hposm2
mva #1 hitclr
#end
#if .byte yschuss4>#207 .or .byte kollm4=#4
ldy yschuss4
dey
lda #0
sta (miss1),y
iny
sta (miss1),y
mva #1 hitclr
mva #8 hposm3
#end
lda blink2
adc #59
sta blink2
#if .byte blink2>=#0 .and .byte blink2<#60
mva #0 blink
#end
#if .byte blink2>=#60 .and .byte blink2<#120
mva #14 blink
#end
#if .byte blink2>=#120 .and .byte blink2<=#180
mva #28 blink
#end
#if .byte blink2>=#180 .and .byte blink2<=#255
mva #42 blink
#end
clc
lda kollp0
cmp #1
bcc @+
mva #0 kollp0
@
jsr letztereihe ;letzte Reihe (lands) Bildschirm1 printen (sichtbar)
jsr feinscroll ;Feinscroll Bildschirm1 ausführen (sichtbar)
mva #$30 var1 ;var1 auf 30000 ($7530) setzen
mva #$75 var1+1
mva #$E4 var2 ;var2 auf 31460 ($7AE4) setzen
mva #$7A var2+1
jsr grobscroll ;Bildschirm1 kopieren + grobscroll
mva #$0C var1 ;var1 + var2 auf 31500 ($7B0C) setzen
mva #$0C var2
mva #$7B var1+1
mva #$7B var2+1
jsr schusslogik
jsr umschalten
inc fuelzaehleritem
lda fuelzaehler
tax
lda fuelzaehleritem
sta 31043,x
sta 32543,x
#if .byte fuelzaehleritem=#155
mva #151 fuelzaehleritem
inc fuelzaehler
#end
#if .byte fuelzaehler>#200
mva #0 fuelzaehler
#end
#if .byte fuelzaehler=#20
mva #52 color3
#end
#if .byte fuelzaehler>#34 .and .byte fuelzaehler<#200
;jmp main1
mva #0 fuelzaehler ;Fuel zuende Neustart
#end
jsr letztereihe
jsr feinscroll ;Feinscroll Bildschirm2 ausführen (sichtbar)
mva #$08 var2 ;var1 auf 29960 ($7508) setzen
mva #$75 var2+1
mva #$0C var1 ;var2 auf 31500 ($7B0C) setzen
mva #$7B var1+1
#if .byte kollges=#4
mva #15 color3
sec
lda fuelzaehler
sbc #10
sta fuelzaehler
tax
mva #151 fuelzaehleritem
clc
lda fuelzaehleritem
@ sta 31043,x
sta 32543,x
inx
cpx #36
bne @-
jsr kollitem
mva #0 kollm1
#end
mva #$08 var2 ;var1 auf 29960 ($7508) setzen
mva #$75 var2+1
mva #$0C var1 ;var2 auf 31500 ($7B0C) setzen
mva #$7B var1+1
jsr grobscroll ;;Bildschirm2 kopieren + grobscroll
mva #$30 var1 ;var1 + var2 auf 30000 ($7530) setzen
mva #$30 var2
mva #$75 var1+1
mva #$75 var2+1
jsr schusslogik
jsr umschalten ;umschalten auf Bildschirm1 - Bildschirm1 wird sichtbar
inc fuelzaehleritem
lda fuelzaehler
tax
lda fuelzaehleritem
sta 31043,x
sta 32543,x
#if .byte fuelzaehleritem=#155
mva #151 fuelzaehleritem
inc fuelzaehler
#end
;Ende der Bildschirmausführung / Kontrolle Durchläufe
sec
lda #45 ; - 36 = Anzahl der Durchläufe - auf 4 beschränkt, da die Landschaft noch rudimentär ist und sich dann wiederholen soll
sbc var6+1
bpl @+
jmp start1 ;Stop hier
@
jmp hauptprogramm ;weiter
.endp
; _____________________________________________________________________________________
;
; ---------------------------- S U B R O U T I N E N ----------------------------------
; _____________________________________________________________________________________
icl 'VBI.asm'
; -------------------------------------------------------------------------------------
.proc kollision
ldx #0
clc
@ inx
cpx #255
bcc @-
rts
.endp
; -------------------------------------------------------------------------------------
.proc umschalten
ldy #4 ;Bildschirme umschalten von unsichtbar auf sichtbar
mva sdlstl var5
mva sdlstl+1 var5+1
lda var1
sta (var5),y
iny
lda var1+1
sta (var5),y
rts
.endp
; -------------------------------------------------------------------------------------
.proc wartes
clc
ldx delay ; Warteschleife
st lda RTCLOK+2
wa cmp RTCLOK+2
beq wa
dex
bpl st
rts
.endp
.proc warte2
clc
@ dec delay1
lda delay1
cmp #1
bne @-
rts
.endp
; -------------------------------------------------------------------------------------
.proc feinscroll
ldy #1
mva #0 delay
mva #255 delay1
@ jsr wartes
sty vscrol
iny
cpy #8
bne @-
rts
.endp
; --------------------------------------------------------------------------------------
.proc schusslogik
#if .byte strig0=#0
asl schussi
#end
#if .byte schussi=#2
lda xposp1
sta hposm0
lda #0
ldy yschuss1
sta (miss1),y
lda yposp1
adc #9
sta yschuss1
asl schussi
#end
#if .byte schussi=#8
lda xposp1
adc #12
sta hposm1
lda #0
ldy yschuss2
sta (miss1),y
lda yposp1
adc #9
sta yschuss2
asl schussi
#end
#if .byte schussi=#32
lda xposp1
sta hposm2
lda #0
ldy yschuss3
sta (miss1),y
lda yposp1
adc #9
sta yschuss3
asl schussi
#end
#if .byte schussi=#128
lda xposp1
adc #12
sta hposm3
lda #0
ldy yschuss4
sta (miss1),y
lda yposp1
adc #9
sta yschuss4
mva #1 schussi
#end
rts
.endp
; --------------------------------------------------------------------------------------
.proc grobscroll
;Den Bildschirm um eins hoch / Grobscrolling um eine Zeile
ldx #22
@ ldy #$28
clc
@ lda (var1),y
sta itemex
#if .byte itemex=#68
jsr fuel
#end
sta (var2),y
dey
bpl @-
clc
lda var1
adc #$28
sta var1
bcc @+
inc var1+1
@ clc
lda var2
adc #$28
sta var2
bcc @+
inc var2+1
@ clc
dex
bpl @-3
rts
.endp
; -------------------------------------------------------------------------------
.proc letztereihe
;Die letzte Reihe printen
;Start der letzten Reihe bei var1 - Line 22
;in Var6 (+1) wird die Position von lands gespeichert
;in Var5 gehen Infos der Boarderanzahl rein
;in y ist der Zähler für letzte Reihe
;x wird als Zähler fürs printen benutzt
lda var1+1
;sta var8+1
;sta var7+1
lda var1
;sta var8
;sta var7
adc #112
sta var1
inc var1+1
inc var1+1
inc var1+1
ldy #0
clc
lda (var6),y ;Boarderanzahl 1 holen
sta var5
tax ;Boarderanzahl 1 in x speichern
jsr var6up
lda (var6),y ;Boarderart 1 holen
sta var7 ;abspeichern in var7
@ iny
sta (var1),y ;Boarder1 printen
dex
bpl @-
jsr var6up
lda (var6),y ;Boarderanzahl 2 holen
tax
jsr var6up
lda (var6),y ;Boarderart 2 holen
ldy var5
@ iny
sta (var1),y ;printen
dex
bpl @-
sty var5 ;Zeilenzähler sichern
jsr var6up
lda (var6),y ;Rand Boarder2 holen
inc var5 ;Zeilenzähler eins weiter
ldy var5
sta (var1),y ;Rand Boarder1 printen
jsr var6up
lda(var6),y ;leer holen
tax
lda #0
ldy var5
@ iny
sta (var1),y ;leer printen
dex
bpl @-
sty var5 ;Zeilenzähler sichern
jsr var6up
lda(var6),y ;Rand Boarder3 holen
ldy var5
iny
sty var5
sta (var1),y ;Rand Boarder3 printen
jsr var6up
lda(var6),y ;Boarder4 holen
tax ;Boarderanzahl in x speichern
jsr var6up
lda (var6),y
ldy var5
@ iny
sta (var1),y ;Boarder4 printen
dex
bpl @-
sty var5 ;Zeilenzähler sichern
jsr var6up
lda(var6),y ;Boarder5 holen
tax ;Boarderanzahl in x speichern
jsr var6up
lda (var6),y
ldy var5
@ iny
sta (var1),y ;Boarder5 printen
dex
bpl @-
jsr var6up
lda (var6),y ;Sonderitem holen
sta var5 ;Item in Var5 speichern
#if .byte var5=#99
jmp *
#end
jsr var6up
#if .byte var5=#50 ;Öltank printen
ldx #11
clc
@ mva tankol,x pr1,x
dex
bpl @-
#if .byte tank1x=#0
mva var1 tank1y
mva var1+1 tank1y+1
sec
lda tank1y
sbc #120
sta tank1y
lda tank1y+1
sbc #0
sta tank1y+1
#end
lda (var6),y ;Startposition des Items in y speichern
sta tank1x
tay
jsr fuel ;Fueltank printen
#end
#if .byte var5=#51 ;Rakete printen
ldx #11
clc
@ mva rakete,x pr1,x
dex
bpl @-
#if .byte tank1x=#0
mva var1 tank1y
mva var1+1 tank1y+1
sec
lda tank1y
sbc #120
sta tank1y
lda tank1y+1
sbc #0
sta tank1y+1
#end
lda (var6),y ;Startposition des Items in y speichern
sta tank1x
tay
jsr fuel ;Rakete printen
#end
#if .byte var5=#52 ;Alien printen
ldx #11
clc
@ mva alien,x pr1,x
dex
bpl @-
#if .byte tank1x=#0
mva var1 tank1y
mva var1+1 tank1y+1
sec
lda tank1y
sbc #120
sta tank1y
lda tank1y+1
sbc #0
sta tank1y+1
#end
lda (var6),y ;Startposition des Items in y speichern
sta tank1x
tay
jsr fuel ;Alien printen
#end
#if .byte var5=#53 ;TNT printen
ldx #11
clc
@ mva tnt,x pr1,x
dex
bpl @-
#if .byte tank1x=#0
mva var1 tank1y
mva var1+1 tank1y+1
sec
lda tank1y
sbc #120
sta tank1y
lda tank1y+1
sbc #0
sta tank1y+1
#end
lda (var6),y ;Startposition des Items in y speichern
sta tank1x
tay
jsr fuel ;TNT printen
#end
jsr var6up
mva #0 vscrol
sec
lda tank1y
sbc #40
sta tank1y
lda tank1y+1
sbc #0
sta tank1y+1
lda tank1x
tay
mva #0 var5
rts
var6up clc
lda var6
adc #1
sta var6
ldy #0
lda var6+1
adc #0
sta var6+1
rts
.endp
; --------------------------------------------------------------------------------------
.proc fuel
sec ;Routine um den Öltank zu printen - es werden 12 Character meanderförmig geprinten 3x4 Matrix
lda var1
sbc #160
sta var2
lda var1+1
sbc #0
sta var2+1
fuelex lda pr1
sta (var2),y ;1
lda pr2
iny
sta (var2),y ;2
lda pr3
iny
sta (var2),y ;3
clc
lda var2
adc #41
sta var2
lda var2+1
adc #0
sta var2+1
dey
lda pr4
sta (var2),y ;4
dey
lda pr5
sta (var2),y ;5
dey
lda pr6
sta (var2),y ;6
clc
lda var2
adc #40
sta var2
lda var2+1
adc #0
sta var2+1
lda pr7
sta (var2),y ;7
lda pr8
iny
sta (var2),y ;8
lda pr9
iny
sta (var2),y ;9
clc
lda var2
adc #40
sta var2
lda var2+1
adc #0
sta var2+1
lda pr10
sta (var2),y ;10
dey
lda pr11
sta (var2),y ;11
dey
lda pr12
sta (var2),y ;12
tya
rts
.endp
; ------------------------------------------------------------------------------
.proc kollitem ;Kollisionsroutine
;var8 unveränderter Bildschirmanfang
lda yschuss1 ;in Gr.0 -32 (sichtbarer Bereich ab 32 und /8
sec
sbc #32
clc
ror
clc
ror
clc
ror
sta yschuss1 ;y-Position in das x-Register schreiben
tax
dex ; und einen abziehen
lda xschuss1 ;x-Position -48 (sichtbarer Bereich)und /4
sec
sbc #48
clc
ror
clc
ror
tay ;in y geht die x-Position
sec
mva var1 var2 ;holen der Bildschirmadresse -> var2
mva var1+1 var2+1
clc
@ lda var2 ;jetzt die y-Position auf die richtige Höhe stellen
adc #40
sta var2
lda var2+1
adc #0
sta var2+1
dex
bpl @- ;die y-Position steht in x - Addition von x Zeilen
@ dey ;die korrekte x-Position einstellen
lda (var2),y ;linken Rand checken
sta var8
iny
iny
lda (var2),y ;rechten Rand checken
sta var9
dey
dey
#if .byte var8=#0 .and .byte var9>#0 ;Position nach rechts anpassen
iny
#end
#if .byte var8>#0 .and .byte var9=#0 ;Position nach links anpassen
dey
#end
lda (var2),y ;2. Durchgang der Anpassung um letzte
sta var8 ;Fehler zu beseitigen
iny
iny
lda (var2),y
sta var9
dey
dey
#if .byte var8=#0 .and .byte var9>#0
iny
#end
#if .byte var8>#0 .and .byte var9=#0
dey
#end
lda (var2),y ;Korrektur der y-Position
sta var8 ;in var8 aktuelle BS-Position
sec
lda var2 ;eins drüber - bleibt wenn var2 zu tief
sbc #40
sta var2
lda var2+1
sbc #0
sta var2+1
lda (var2),y ;lade Bildschirminhalt eins drüber
sta var9 ;das geht in var9 rein
#if .byte var8>#0 .and .byte var9=#0 ;alte Position var2
clc ;wiederherstellen
lda var2
adc #40
sta var2
lda var2+1
adc #0
sta var2+1
#end
#if .byte var8=#0 .and .byte var9=#0 ;alte Position var2
clc ;eins runter
lda var2
adc #80
sta var2
lda var2+1
adc #0
sta var2+1
#end
lda (var2),y ;2. Durchgang der Anpassung um letzte
sta var8 ;Fehler zu beseitigen
sec
lda var2
sbc #40
sta var2
lda var2+1
sbc #0
sta var2+1
lda (var2),y
sta var9
#if .byte var8>#0 .and .byte var9=#0
clc
lda var2
adc #40
sta var2
lda var2+1
adc #0
sta var2+1
#end
#if .byte var8=#0 .and .byte var9=#0
clc
lda var2
adc #80
sta var2
lda var2+1
adc #0
sta var2+1
#end
;ab hier stimmt die Position des Items (meistens)
;in der Variable y für x-Position
;und in var2 für die y-Position
expl11
mva var2 tank1pos ;y-Position für Explosion1
mva var2+1 tank1pos+1
ldx #11
clc
@ mva expl1,x pr1,x
dex
bpl @-
jsr fuel.fuelex
tay
iny
expl22
mva #80 var5
mva tank1pos var2
mva tank1pos+1 var2+1
mva #1 delay
jsr wartes
ldx #11
clc
@ mva expl2,x pr1,x
dex
bpl @-
jsr fuel.fuelex
tay
iny
expl33
mva #92 var5
mva tank1pos var2
mva tank1pos+1 var2+1
mva #1 delay
jsr wartes
ldx #11
clc
@ mva expl3,x pr1,x
dex
bpl @-
jsr fuel.fuelex
tay
iny
expl44
mva #104 var5
mva tank1pos var2
mva tank1pos+1 var2+1
mva #1 delay
jsr wartes
ldx #11
clc
@ mva expl4,x pr1,x
dex
bpl @-
jsr fuel.fuelex
tay
iny
rts
.endp
; ------------------------------------------------------------------------------
.proc schuesse
ldy yschuss1
iny
iny
lda #1
sta (miss1),Y
sty yschuss1
lda #0
dey
dey
sta (miss1),Y
mva m0pf kollm1
ldy yschuss2
iny
iny
lda #4
sta (miss1),Y
sty yschuss2
lda #0
dey
dey
sta (miss1),Y
mva m1pf kollm2
ldy yschuss3
iny
iny
lda #16
sta (miss1),Y
sty yschuss3
lda #0
dey
dey
sta (miss1),Y
mva m2pf kollm3
ldy yschuss4
iny
iny
lda #64
sta (miss1),Y
sty yschuss4
lda #0
dey
dey
sta (miss1),Y
mva m3pf kollm4
rts
.endp
.proc text
ldx #0
lda #52
jsr prte
inx
lda #45
jsr prte
inx
lda #54
jsr prte
inx
lda #31
jsr prte
inx
lda #52
jsr prte
inx
lda #49
jsr prte
inx
lda #0
jsr prte
inx
lda #54
jsr prte
inx
lda #50
jsr prte
inx
lda #0
jsr prte
inx
lda #51
jsr prte
inx
lda #47
jsr prte
inx
lda #50
jsr prte
inx
lda #42
jsr prte
inx
lda #50
jsr prte
inx
lda #53
jsr prte
inx
lda #0
jsr prte
inx
lda #55
jsr prte
inx
lda #34
jsr prte
inx
lda #32
jsr prte
inx
lda #34
jsr prte
inx
lda #34
jsr prte
inx
lda #0
jsr prte
inx
lda #51
jsr prte
inx
lda #45
jsr prte
inx
lda #54
jsr prte
inx
lda #45
jsr prte
inx
lda #52
jsr prte
inx
lda #0
jsr prte
inx
lda #51
jsr prte
inx
lda #52
jsr prte
inx
lda #50
jsr prte
inx
lda #44
jsr prte
inx
lda #45
jsr prte
inx
lda #47
jsr prte
inx
lda #48
jsr prte
inx
lda #0
jsr prte
ldx #0 ;Fuel
lda #46
jsr prte2
inx
lda #31
jsr prte2
inx
lda #45
jsr prte2
inx
lda #48
jsr prte2
ldx #10 ;Score
lda #53
jsr prte2
inx
lda #43
jsr prte2
inx
lda #50
jsr prte2
inx
lda #52
jsr prte2
inx
lda #45
jsr prte2
inx
lda #0
jsr prte2
inx
lda #160
jsr prte2
inx
lda #32
jsr prte2
inx
lda #32
jsr prte2
inx
lda #32
jsr prte2
ldx #23 ;Ships
lda #53
jsr prte2
inx
lda #47
jsr prte2
inx
lda #33
jsr prte2
inx
lda #51
jsr prte2
inx
lda #53
jsr prte2
inx
lda #0
jsr prte2
inx
lda #28
jsr prte2
inx
lda #29
jsr prte2
inx
lda #0
jsr prte2
inx
lda #28
jsr prte2
inx
lda #29
jsr prte2
inx
lda #0
jsr prte2
inx
lda #28
jsr prte2
inx
lda #29
jsr prte2
ldx #0
fuellauf
clc
lda fuelzaehleritem
@ jsr prte3
inx
cpx #36
bne @-
rts
prte sta 30923,x
sta 32423,x
rts
prte2 sta 31003,x
sta 32503,x
rts
prte3 sta 31043,x
sta 32543,x
rts
.endp
; ------------------------------------------------------------------------------
run main
und noch ein kleines Video:
und nun das Problem:
Es sind die Kollisionen... Die Missiles laufen ja im VBI und erkennen dort auch die Kollisionen. Wenn jetzt im Hauptprogramm die Abfragen kommen und die verschiedenen Aktionen der jeweiligen Kollision, ist der Missile ja bevor überhaupt was passiert im VBI schon ein paar Zeilen weitergegangen und hat dann schon ganz andere Kollisionen gemacht bzw. die eigentliche Aktion kommt im Hauptprogramm zu spät.... ich habe heute einige Stunden mit allen möglichen Varianten experimentiert aber keine gute Lösung gefunden. Programmiere ich die ganze Schusslogik im Hauptprogramm, laufen die Missiles zu langsam und ruckeln. Programmiere ich alles im VBI dann verbrauche ich dort wieder zu viel Zeit. Ich fürchte aber es geht nicht anders... Oder übersehe ich da etwas?? LG Peter
Hi!
Evtl. geht ja ein Gemisch? Im VBI wird die Kollision erkannt und der Missile ausgeblendet. Du setzt eine Variable Kollision auf true und merkst Dir die Position der Kollision. Im Hauptprogramm erkennst Du nun die Kollision und die Position und kümmerst Dich um die weitere Logik.
Wenn die Animation der Kollision minimal verzögert kommt, sollte das kein Problem sein. Der Schuss ist weg und somit optisch kollidiert.
Grüße Janko
Meine Projekte findest Du hier...
Hallo Janko, wo kommst du nochmal her?? Vielleicht sollten wir mal ein Projekt zusammen machen, ich glaube wir ticken ganz ähnlich. Ich habe mir natürlich auch nebenher Gedanken gemacht, wie ich das lösen kann und bin auf den gleichen Ansatz gekommen.
Die Schüsse müssen gut laufen und die Kollisionen müssen stabil klappen, sonst geht ja der Spielspass flöten. Also habe ich mir jetzt gesagt: VBI erstmal egal, ich muss da noch mehr Code reinpacken. Das habe ich jetzt auch umgesetzt und es jetzt so zunächst gelöst: Die Missiles laufen ja ständig im VBI unsichtbar und ich biege nur die x- und y-Position jeweils um, wenn der Feuerknopf gedrückt wird. Für die Abfolge der Schüsse nehme ich eine Extravariable, da steht eine 1 drin, die mit dem Befehl ASL bitweise verschoben wird. Das steuert die Schüsse in der Folge rechts links rechts links. Diese Schusslogik findet im Hauptprogramm statt. Damit die Schüsse schneller laufen, incrementiere ich sie im VBI 2x - das Problem dabei ist, daß dann 2 verschiedene Kollisionen stattfinden können. Eine gewollte und eine ungewollte. Dafür halte ich 4x2 Variablen bereit und packe die jeweilige Kollisionsart in diese Variable rein - für alle 4 Schüsse. Das läuft auch ständig im VBI. Sobald eine Kollision eines Missiles stattfindet, biege ich den x-Vektor dieses Missiles im VBI weg, damit dann keine weiteren Kollisionen stattfinden können und die ersten Ereignisse überschreiben können. Dieser Aufwand muss wohl im VBI sein, vielleicht kann ich den Code noch etwas optimieren. Alles andere muss dann im Hauptprogramm erfolgen. Wahrscheinlich muss ich im VBI auch noch die jeweiligen x und y-Positionen retten!
Das System ist zunehmend sensibel finde ich. Nach diesen Änderungen bekomme ich ab und zu ein unangenehmes Ruckeln rein - mal ja und mal nicht. Habe noch nicht rausgefunden woher das kommt.... ich dachte erst an der Lände des VBI, aber wenn ich den Emulator auf 60 Hz umstelle, läuft es stabiler - dann kann es ja nicht an der Codelänge im VBI liegen.
Ganz schön kompliziert so ein Shooter....... ich glaube als nächstes Projekt mache ich mal ein feines Jump ´n Run - Spiel 😉 Gruß Peter
;Schüsse 1-4 laufen incl. Kollisionsabfragen
lda #1
ldy yschuss1
iny
sta (miss1),Y
mva m0pf kollm1
lda #1
iny
sta (miss1),y
mva m0pf kollm12
sty yschuss1
lda #0
dey
dey
sta (miss1),Y
iny
sta (miss1),y
lda #4
ldy yschuss2
iny
sta (miss1),Y
mva m1pf kollm2
lda #4
iny
sta (miss1),y
mva m1pf kollm22
sty yschuss2
lda #0
dey
dey
sta (miss1),Y
iny
sta (miss1),y
lda #16
ldy yschuss3
iny
sta (miss1),Y
mva m2pf kollm3
lda #16
iny
sta (miss1),y
mva m2pf kollm32
sty yschuss3
lda #0
dey
dey
sta (miss1),Y
iny
sta (miss1),y
lda #64
ldy yschuss4
iny
sta (miss1),Y
mva m3pf kollm4
lda #64
iny
sta (miss1),y
mva m3pf kollm42
sty yschuss4
lda #0
dey
dey
sta (miss1),Y
iny
sta (miss1),y
mva #1 hitclr
Ich habe jetzt mal rumexperimentiert, aber dieses Bildschirmruckeln ist blöd, da es auch dann ab und zu Fehler in der Landschaft produziert. Ich kann es auch kaum reproduzieren... manchmal ruckelt es stark und manchmal gar nicht.
Heute habe ich dann auf 2 Schüsse verzichtet und somit den Code im VBI deutlich reduziert - das Ruckeln ist weg. Auch habe ich die komplizierten If Then Or Schleifen weggelassen und es nativ programmiert - in der Hoffnung, daß es stabiler läuft. Fazit: Weniger Code im VBI stabilisiert das System, aber auch mit 2 Schüssen scheine ich nicht viel Luft zu haben, was seltsam anmutet... habe ich mich verrechnet? Ich war von ca. 1500 Befehlen - also 7000-8000 Taktzyklen ausgegangen. Mit 4 Schüssen verbrauche ich 610 Befehle, mit 2S Schüssen nur 380 Befehle - also noch viel Luft nach oben. Woran hängt es dann? Schafft der Rechner zwar die 610 Befehle ohne dass er abstürzt aber mit zunehmender Belastung des VBI wird das System instabil??? So bekomme ich keinen vernünftigen Sound mehr rein... Oder habe ich irgendwo einen Denkfehler?? Muss ich ganz gezielt WSYNC einsetzen (alle Versuche machte es eher schlechter). Ist meine Lösung mit dem Fein-/Grobscroll mit 2 Bildschirmen zu instabil??? Wie bloß haben die Jungs das früher programmiert und die Shooter so schön hinbekommen?? Für Ideen bin ich echt dankbar! Gruß Peter
hier das Video mit 2 Schüssen:
und das Video mit 4 Schüssen:
in beiden Fällen wird die Kollision noch nicht richtig erkannt und die Explosion läuft nicht richtig... aber das muss ich ja noch anpassen!
Hallo Peter,
hier mal ein theoretischer Ansatz, ohne Gewähr auf Richtigkeit 😉
Der ATARI läuft zwar mit ca. 1,79Mhz, aber den größten Teil ist die CPU blockiert, damit die Grafik dargestellt werden kann. Die meiste "freie" Zeit hat der ATARI wenn das Bild gerade fertig aufgebaut wurde und ein neuer Aufbau vorbereitet wird. Das ist dann auch die Zeit des VBI. Also je mehr Code im VBI ausgeführt wird, desto weniger kann der ATARI außerhalb des VBI bearbeiten.
Der VBI wird alle 1/50 Sekunde aufgerufen. Das heißt alles im VBI wird alle 20ms erneut ausgeführt.
Die Frage ist somit, muss wirklich alles immer 50x die Sekunde abgearbeitet werden? Kann man vllt. Code aufteilen, so dass im 1. VBI Teil A, im 2. VBI Teil B und im 3. VBI Teil C bearbeitet wird, und dann wieder von vorne? Nur wichtiger Code wird jedes Mal ausgeführt.
Beispiel Scrolling im VBI: 1. VBI - Feinscolling +1 im sichtbaren Bereich und 256 Byte im ausgeblendeten wird verschoben. 2. VBI - Feinscolling +1 im sichtbaren Bereich und weitere 256 Byte im ausgeblendeten wird verschoben. 3. VBI - Feinscolling +1 im sichtbaren Bereich und weitere 256 Byte im ausgeblendeten wird verschoben. 4. VBI - Feinscolling +1 im sichtbaren Bereich und die letzen 256 Byte im ausgeblendeten wird verschoben. 5. VBI - Feinscolling +1 die letzte Zeile wird aus den Daten erzeugt 6. VBI - Feinscolling +1 Objekte werden entfernt, die bereits abgeschossen wurden 7. VBI - Feinscolling +1 Punktestand und Fuel etc. werden ausgegeben/aktualisiert 8. VBI - Feinscolling wieder zurücksetzen und umblenden
Hoffentlich habe ich jetzt nicht zu viel Mist erzählt und Du kannst damit etwas anfangen 🙂
Grüße Janko
Meine Projekte findest Du hier...
Hi Janko, erst einmal vielen Dank für den wirklich kreativen Ansatz. Ich dachte wirklich in dem Moment, als ich es gelesen hatte: Das ist es. Und habe es gerade mal mit einfacher Teilung des VBI umgesetzt... so einfach geht es leider nicht. Es ruckelt mindestens genauso und die Steuerung und die Missiles laufen abgehackt. Vielleicht kann man das noch besser umsetzten, wird aber richtig kompliziert... der VBI, gesteuert durch das Hauptprogramm geht nicht gut, aber.... er läßt sich steuern und aufrufen durch den DLI und dann kann ich den VBI in Portionen teilen und jeweils aufrufen.
Und dann fiel mir noch folgendes ein: Warum nicht einfach den VBI2 durch den VBI1 aufrufen und dann VBI3 durch VBI2 usw..... das habe ich gerade mal umgesetzt und einen schönen Systemabsturz erwartet... aber siehe da: Es funktioniert. Und läuft flüssig und mit 4 Schüssen ganz ohne ruckeln!! Wie cool !! Ok, die Steuerung ist natürlich etwas träger und die Missiles laufen etwas langsamer runter - das muss ich noch anpassen. Aber zumindest ist das wohl die Lösung der Probleme. Hurra!!!!! Gruß Peter
... Danke für die notwendige Inspiration!!
... heute habe ich eine Menge experimentiert mit den VBI´s.... folgendes kann ich nun berichten:
Zeit bleibt Zeit und das kann man nicht ändern. Teile ich den langen VBI in 2 VBI´s, dann läuft das System stabil und rund, aber man merkt die Einbuße der Geschwindigkeit. Die Joysticksteuerung wird etwas träger und ich muss die x- und y-Verschiebung des Raumschiffes anpassen (Werte verdoppeln). Dadurch läuft es noch gut aber nicht mehr ganz so flüssig. Gleiches gilt für die Missiles... auch hier musste ich die Geschwindigkeit verdoppeln, da sonst die Missiles zu langsam runterlaufen. Ich kann noch weitere VBI´s einbauen und so weiter "teilen" - Thema Musik, das wird alles andere aber logischerweise weiter verlangsamen... hier gibt es also ganz klar Grenzen!! Ich lass das jetzt erst einmal so und mache weiter. Am Ende schaue ich, daß ich noch ein wenig Code vom VBI ins Hauptprogramm packe... vielleicht experimentiere ich auch noch mit dem DLI - aber der ist ja noch zeitkritischer.
Immerhin kann man eines sagen: Einen VBI durch einen anderen VBI aufzurufen geht einfach und gut, man kann da direkt den Vektor umbiegen und muss nicht erst durch setvbv durchspringen... anbei das vorläufige Listing des VBI:
.proc vbinter
pha
txa
pha
tya
pha
mva #0 atract ;Bildschirmschoner aus
clc ;Kollisionen abfragen
lda p0pf
cmp #1
bcc @+
mva #1 kollp0
@
clc ;Joystickabfragen Player1
lda stick0
cmp #15 ;keine Joystickaktion
bcs @+
cmp #14
bcs nachob
cmp #13
bcs nachun1
cmp #11
bcs nachli
cmp #10
bcs nachliob
cmp #9
bcs nachliun
sec
cmp #7
bcs nachre
cmp #6
bcs nachreob
cmp #5
bcs nachreun
@ jmp write
nachun1 jmp nachun
nachre clc
lda xposp1
cmp #192
bcs @+
inc xposp1
inc xposp1
@ jmp write
nachreun
clc
lda xposp1
cmp #192
bcs @+
inc xposp1
inc xposp1
@ jmp nachun
nachreob
clc
lda xposp1
cmp #192
bcs @+
inc xposp1
inc xposp1
@ jmp nachob
nachli sec
lda xposp1
cmp #49
bcc @+
dec xposp1
dec xposp1
@ jmp write
nachliun
sec
lda xposp1
cmp #49
bcc @+
dec xposp1
dec xposp1
@ jmp nachun
nachliob
sec
lda xposp1
cmp #49
bcc @+
dec xposp1
dec xposp1
@ jmp nachob
nachob
dec yposp1
clc
ldy yposp1 ;verticale Startpos. Player 1 + füllen
ldx #0
@ lda pm1,x
sta (play1),y
iny
inx
cpx #14
bne @-
jmp write
nachun
inc yposp1
clc
ldy yposp1 ;verticale Startpos. Player 1 + füllen
ldx #0
@ lda pm1,x
sta (play1),y
iny
inx
cpx #14
bne @-
jmp write
clc
write sec
lda xposp1 ;x-Position der Player setzen
sta hposp0
sbc #0
sta hposp2
adc #2
sta hposp3
ldy yposp1 ;Player printen
clc
lda blink
tax
dey
mva #0 lms2
@ lda pm41,x
sta (play4),y
lda pm42,x
sta (play3),y
iny
inx
inc lms2
lda lms2
cmp #14
bne @-
mwa #vbinter2 $224
pla
tay
pla
tax
pla
jmp xitvbv ;vb-interrupt wird über xitvbv beendet!!
.endp
.proc vbinter2
pha
txa
pha
tya
pha
;Schüsse 1-4 laufen incl. Kollisionsabfragen
lda #1
ldy yschuss1
iny
iny
sta (miss1),Y
mva m0pf kollm1
lda #1
iny
sta (miss1),y
mva m0pf kollm12
sty yschuss1
lda #0
dey
dey
dey
sta (miss1),Y
iny
iny
sta (miss1),y
lda #4
ldy yschuss2
iny
iny
sta (miss1),Y
mva m1pf kollm2
lda #4
iny
sta (miss1),y
mva m1pf kollm22
sty yschuss2
lda #0
dey
dey
dey
sta (miss1),Y
iny
iny
sta (miss1),y
lda #16
ldy yschuss3
iny
iny
sta (miss1),Y
mva m2pf kollm3
lda #16
iny
sta (miss1),y
mva m2pf kollm32
sty yschuss3
lda #0
dey
dey
dey
sta (miss1),Y
iny
iny
sta (miss1),y
lda #64
ldy yschuss4
iny
iny
sta (miss1),Y
mva m3pf kollm4
lda #64
iny
sta (miss1),y
mva m3pf kollm42
sty yschuss4
lda #0
dey
dey
dey
sta (miss1),Y
iny
iny
sta (miss1),y
mva #1 hitclr
#if .byte kollm1>#0 .or .byte kollm12>#0
mva hposm0 xschuss
mva yschuss1 yschuss
mva #8 hposm0
mva kollm1 kollges
mva kollm12 kollges2
#end
#if .byte kollm2>#0 .or .byte kollm22>#0
mva #8 hposm1
mva kollm2 kollges
mva kollm22 kollges2
#end
#if .byte kollm3>#0 .or .byte kollm32>#0
mva #8 hposm2
mva kollm3 kollges
mva kollm32 kollges2
#end
#if .byte kollm4>#0 .or .byte kollm42>#0
mva #8 hposm3
mva kollm4 kollges
mva kollm42 kollges2
#end
mwa #vbinter $224
pla
tay
pla
tax
pla
jmp xitvbv ;vb-interrupt wird über xitvbv beendet!!
.endp
Ich hoffe ich nerve oder langweile hier keinen mit meinem Projekt - allerdings, muss man ja auch nicht lesen ... 😉
Mein Zwischenfazit bislang:
- Ich lerne jeden Tag den Atari besser kennen und werde immer sicherer in Assembler.
- Es gibt unglaublich viele Möglichkeiten und aber auch Tücken - mein Respekt gegenüber den Programmierern von damals ist deutlich gestiegen - toll, was die aus der Kiste rausgeholt haben!
- Wir haben ganz klare Limitationen hinsichtlich Zeit und Größe des Programmes - es geht vieles aber nicht alles und man muss sein Projekt wirklich sehr gut planen.
- Und genau das macht es aus... sich ständig neuen Herausforderungen ausgesetzt sehen, grübeln grübel grübeln und Lösungen finden und umsetzen. Und genau darum haben die meisten alten Programme auch so viel Charme - nämlich weil da so viel Arbeit, Hirnschmalz und Liebe drinsteckt....
- Mein Projekt wird wohl noch einige Monate verschlingen, denn es soll gut und spielbar werden... und dann freue ich mich schon auf das nächste schöne Projekt, wo ich viele Dinge primär ganz anders plane....
Gruß Peter
Hi Peter, deine Berichte sind spannend, auch wenn ich noch nie ein Spiel geschrieben habe.
Zu deinen permanenten Zeitproblemen im VBI folgende Idee, die aber evtl. auch vollkommen sinnlos ist:
Das Hauptprogramm ist nach meinem Verständnis üblicherweise eine Dauerschleife. So ungefähr:
main jsr tue_dieses
jsr tue_jenes
jsr mach_was_tolles
jmp main
Wenn du jetzt die Dinge, die nicht innerhalb des VBI, sondern nur je einmal pro VBI ablaufen sollen, in eine diese Unterroutinen legst und dort verifizierst, dass sie nur einmal je VBI ausgeführt wird, solltest du eine ganze Menge Zeit zur Verfügung haben.
tue_jenes
lda RTCLOK+2 ; wird im Stage 1 VBI automatisch inkrementiert
cmp letztes_mal
bne mach_weiter
rts
mach_weiter
sta letztes_mal
; Mach all die tollen Dinge, für die im VBI keine Zeit ist
rts
letztes_mal
.byte $00
Hi. Ich finde es auch interessant wie das Spiel entsteht. Und stark ist auch das Peter es gleich in Assembler angeht. Aber learning by doing, wie man so schön sagt. Durchhaltevermögen ist ja scheinbar da.
Ich habe heute von Cas ein paar Zong-Hefte bekommen und durchgeblättert. Da sind immer Berichte/Kurs zu Assembler drin. Interessant könnte die Ausgabe 3-4/94 sein. Da geht es um Scrolling in Assembler. Am Ende wird ein Beispiel vorgestellt in dem in einer Landschaft rumgescrollt wird. Zwar rechts/links, aber besser wie nix 😁 . In der nächsten Ausgabe sollte das weiter entwickelt werden, aber die habe ich nicht. Gibt es aber bestimmt irgendwo online. Disketten gab es auch dazu. In einer Ausgabe war auch eine PM-Routine drin, aber nur auf Diskette.
Kannst ja mal nachlesen. Vielleicht hilft ja das eine oder andere was.
Gruß Wolfgang
... Ihr Lieben, vielen Dank für die Rückmeldungen und vielen Ideen. Das tut gut und spornt an... und alle Ideen und Tips sind mehr als willkommen. Zong Hefte .... ich suche mal! Schönen Abend allen! Gruß Peter
Was macht mein kleines Projekt? In den letzten Wochen hatte ich sehr viel an verschiedenen Dingen programmiert und experimentiert... und mich ein wenig verrannt. Ich bin dann mal einen Schritt zurückgegangen und habe eine etwas ältere aber stabil funktionierende Version genommen und da weitergearbeitet. Ich kann jetzt nicht das ganze Programm komplett ändern, möchte es aber fertigstellen und es funktioniert dann nach den ursprünglichen Kriterien. Ich habe nicht 4 sondern nur 2 Schüsse und die laufen abwechselnd und nicht zugleich. Das war das ursprüngliche Konzept und dabei bleibt es jetzt. Der VBI ist etwas schlanker geworden, aber noch recht voll. Da passt nicht mehr viel rein, braucht es aber auch nicht. Die Schüsse funktionieren jetzt und auch die leidliche Kollision funktioniert zu 98% ohne Fehler. Es gibt jetzt einen ständigen Hintergrundsound, die Explosion der Items funktioniert stabil und mit Sound und die Schüsse laufen jetzt auch mit Sound. Am Sound werde ich später noch arbeiten und vielleicht implementiere ich noch die xSFX Engine ins Programm. Die jetzige Engine ist brutal einfach und mini... geht aber zunächst.
Bevor ich dann mit der Landschaftsgestaltung weitermache und dann noch die nächsten Features reinbringe, will ich nochmal die Explosion angehen. Das gefällt mir noch nicht, da eine Explosion immer zu einem kleinen Programmstop führt. Meine Idee dafür sieht folgendermaßen aus: Im Moment printet das Programm hintereinander mit kleiner Warteschleife die 4 Explosionsphasen über das Item bis es weg ist... Phase 4 ist alles 0 also weg. Die Lösung soll so sein: Die Explosion wird erkannt, das Item wird mit dem ersten Explosionscharakterset überschrieben, dann wird der erste Explosionscharakterset während das Programm weiterläuft mit den 3 weiteren Phasen überschrieben und so läuft die Explosion weiter während das ganze Programm weiterläuft. Theorie glasklar, Umsetzung nicht ganz einfach, da auch das ganze Timing stimmen muss..... Zum Glück habe ich seit einer Woche Freund Omikron in den Knochen und bin entsprechend zuhause und finde etwas Zeit das zu programmieren....
Gruß Peter
der Code im Hauptprogramm:
org $2000
icl '../hardware.txt'
icl 'header.txt'
icl 'character.asm'
icl 'lands.asm'
icl 'pmg_vars.asm'
icl 'VBI.asm'
.proc main
main1 mwa #dlist 560
mva #151 fuelzaehleritem
mva #0 fuelzaehler
mva #10 store1
mva #170 store3
mva #16 sound12
jsr text
Start1
jsr variablensetzen
jsr pmvorbereiten
ldy #0
ldx #0
ldx #>vbinter ;VB-Interrupt VektorHi
ldy #<vbinter ;VB-Interrupt VektorLo
lda #7 ;Deferred Mode mit lda #7 festlegen
jsr setvbv ;Vektor für die eigene Routine über setvbv eintragen
hauptprogramm
;jsr kollplayer
jsr soundschuss
jsr blinken
jsr letztereihe ;letzte Reihe (lands) Bildschirm1 printen (sichtbar)
jsr feinscroll ;Feinscroll Bildschirm1 ausführen (sichtbar)
jsr grobscroll ;Bildschirm1 kopieren + grobscroll
jsr umschalten
jsr incfuelzaehler
jsr kollmissile
;Ende der Bildschirmausführung / Kontrolle Durchläufe
sec
lda #45 ; - 36 = Anzahl der Durchläufe - auf 4 beschränkt, da die Landschaft noch rudimentär ist und sich dann wiederholen soll
sbc var6+1
bpl @+
jmp start1 ;Stop hier
@ jmp hauptprogramm ;weiter
.endp
; ---------------------------- S U B R O U T I N E N ----------------------------------
.proc kollplayer
clc
lda kollp0
cmp #1
bcc @+
mva #0 kollp0
@ rts
.endp
.proc kollision
ldx #0
clc
@ inx
cpx #255
bcc @-
rts
.endp
.proc umschalten
ldy #4 ;Bildschirme umschalten von unsichtbar auf sichtbar
mva sdlstl var5
mva sdlstl+1 var5+1
lda var1
sta (var5),y
iny
lda var1+1
sta (var5),y
rts
.endp
.proc wartes
clc
ldx delay ; Warteschleife
st lda RTCLOK+2
wa cmp RTCLOK+2
beq wa
dex
bpl st
rts
.endp
.proc warte2
clc
@ dec delay1
lda delay1
cmp #1
bne @-
rts
.endp
.proc feinscroll
ldy #1
mva #0 delay
mva #255 delay1
@ jsr wartes
sty vscrol
iny
cpy #8
bne @-
inc schussi
#if .byte schussi=#1
mwa #$7508 var2 ;var1 auf 29960 ($7508) setzen
mwa #$7b0C var1
#end
#if .byte schussi=#2
mwa #$7530 var1 ;var1 auf 30000 ($7530) setzen
mwa #$7AE4 var2 ;var2 auf 31460 ($7AE4) setzen
#end
rts
.endp
.proc schusslogik
#if .byte strig0=#0
asl schussi
#end
#if .byte schussi=#2
lda xposp1
sta hposm0
lda #0
ldy yschuss1
sta (miss1),y
lda yposp1
adc #9
sta yschuss1
asl schussi
mva #1 schussi
#end
#if .byte schussi=#8
lda xposp1
adc #12
sta hposm1
lda #0
ldy yschuss2
sta (miss1),y
lda yposp1
adc #9
sta yschuss2
mva #1 schussi
#end
rts
.endp
.proc grobscroll
;Den Bildschirm um eins hoch / Grobscrolling um eine Zeile
ldx #22
@ ldy #$28
clc
@ lda (var1),y
sta itemex
#if .byte itemex=#68
jsr fuel
#end
sta (var2),y
dey
bpl @-
clc
lda var1
adc #$28
sta var1
bcc @+
inc var1+1
@ clc
lda var2
adc #$28
sta var2
bcc @+
inc var2+1
@ clc
dex
bpl @-3
#if .byte schussi=#1
mwa #$7530 var1 ;var1 + var2 auf 30000 ($7530) setzen
mwa #$7530 var2
#end
#if .byte schussi=#$2
mwa #$7b0C var1 ;var1 + var2 auf 31500 ($7B0C) setzen
mwa #$7b0C var2
mva #0 schussi
#end
rts
.endp
.proc letztereihe
;Die letzte Reihe printen
;Start der letzten Reihe bei var1 - Line 22
;in Var6 (+1) wird die Position von lands gespeichert
;in Var5 gehen Infos der Boarderanzahl rein
;in y ist der Zähler für letzte Reihe
;x wird als Zähler fürs printen benutzt
clc
lda var1+1
;sta var8+1
;sta var7+1
lda var1
;sta var8
;sta var7
adc #112
sta var1
inc var1+1
inc var1+1
inc var1+1
ldy #0
clc
lda (var6),y ;Boarderanzahl 1 holen
sta var5
tax ;Boarderanzahl 1 in x speichern
jsr var6up
lda (var6),y ;Boarderart 1 holen
sta var7 ;abspeichern in var7
@ iny
sta (var1),y ;Boarder1 printen
dex
bpl @-
jsr var6up
lda (var6),y ;Boarderanzahl 2 holen
tax
jsr var6up
lda (var6),y ;Boarderart 2 holen
ldy var5
@ iny
sta (var1),y ;printen
dex
bpl @-
sty var5 ;Zeilenzähler sichern
jsr var6up
lda (var6),y ;Rand Boarder2 holen
inc var5 ;Zeilenzähler eins weiter
ldy var5
sta (var1),y ;Rand Boarder1 printen
jsr var6up
lda(var6),y ;leer holen
tax
lda #0
ldy var5
@ iny
sta (var1),y ;leer printen
dex
bpl @-
sty var5 ;Zeilenzähler sichern
jsr var6up
lda(var6),y ;Rand Boarder3 holen
ldy var5
iny
sty var5
sta (var1),y ;Rand Boarder3 printen
jsr var6up
lda(var6),y ;Boarder4 holen
tax ;Boarderanzahl in x speichern
jsr var6up
lda (var6),y
ldy var5
@ iny
sta (var1),y ;Boarder4 printen
dex
bpl @-
sty var5 ;Zeilenzähler sichern
jsr var6up
lda(var6),y ;Boarder5 holen
tax ;Boarderanzahl in x speichern
jsr var6up
lda (var6),y
ldy var5
@ iny
sta (var1),y ;Boarder5 printen
dex
bpl @-
jsr var6up
lda (var6),y ;Sonderitem holen
sta var5 ;Item in Var5 speichern
#if .byte var5=#99
jmp *
#end
jsr var6up
#if .byte var5=#50 ;Öltank printen
ldx #11
clc
@ mva tankol,x pr1,x
dex
bpl @-
#if .byte tank1x=#0
mva var1 tank1y
mva var1+1 tank1y+1
sec
lda tank1y
sbc #120
sta tank1y
lda tank1y+1
sbc #0
sta tank1y+1
#end
lda (var6),y ;Startposition des Items in y speichern
sta tank1x
tay
jsr fuel ;Fueltank printen
#end
#if .byte var5=#51 ;Rakete printen
ldx #11
clc
@ mva rakete,x pr1,x
dex
bpl @-
#if .byte tank1x=#0
mva var1 tank1y
mva var1+1 tank1y+1
sec
lda tank1y
sbc #120
sta tank1y
lda tank1y+1
sbc #0
sta tank1y+1
#end
lda (var6),y ;Startposition des Items in y speichern
sta tank1x
tay
jsr fuel ;Rakete printen
#end
#if .byte var5=#52 ;Alien printen
ldx #11
clc
@ mva alien,x pr1,x
dex
bpl @-
#if .byte tank1x=#0
mva var1 tank1y
mva var1+1 tank1y+1
sec
lda tank1y
sbc #120
sta tank1y
lda tank1y+1
sbc #0
sta tank1y+1
#end
lda (var6),y ;Startposition des Items in y speichern
sta tank1x
tay
jsr fuel ;Alien printen
#end
#if .byte var5=#53 ;TNT printen
ldx #11
clc
@ mva tnt,x pr1,x
dex
bpl @-
#if .byte tank1x=#0
mva var1 tank1y
mva var1+1 tank1y+1
sec
lda tank1y
sbc #120
sta tank1y
lda tank1y+1
sbc #0
sta tank1y+1
#end
lda (var6),y ;Startposition des Items in y speichern
sta tank1x
tay
jsr fuel ;TNT printen
#end
jsr var6up
mva #0 vscrol
sec
lda tank1y
sbc #40
sta tank1y
lda tank1y+1
sbc #0
sta tank1y+1
lda tank1x
tay
mva #0 var5
rts
var6up clc
lda var6
adc #1
sta var6
ldy #0
lda var6+1
adc #0
sta var6+1
rts
.endp
.proc fuel
sec ;Routine um den Öltank zu printen - es werden 12 Character meanderförmig geprinten 3x4 Matrix
lda var1
sbc #160
sta var2
lda var1+1
sbc #0
sta var2+1
fuelex lda pr1
sta (var2),y ;1
lda pr2
iny
sta (var2),y ;2
lda pr3
iny
sta (var2),y ;3
clc
lda var2
adc #41
sta var2
lda var2+1
adc #0
sta var2+1
dey
lda pr4
sta (var2),y ;4
dey
lda pr5
sta (var2),y ;5
dey
lda pr6
sta (var2),y ;6
clc
lda var2
adc #40
sta var2
lda var2+1
adc #0
sta var2+1
lda pr7
sta (var2),y ;7
lda pr8
iny
sta (var2),y ;8
lda pr9
iny
sta (var2),y ;9
clc
lda var2
adc #40
sta var2
lda var2+1
adc #0
sta var2+1
lda pr10
sta (var2),y ;10
dey
lda pr11
sta (var2),y ;11
dey
lda pr12
sta (var2),y ;12
tya
rts
.endp
.proc kollitem
;var8 unveränderter Bildschirmanfang
lda yschuss1 ;in Gr.0 -32 (sichtbarer Bereich ab 32 und /8
sec
sbc #32
clc
ror
clc
ror
clc
ror
sta yschuss1 ;y-Position in das x-Register schreiben
tax
dex ; und einen abziehen
lda xschuss1 ;x-Position -48 (sichtbarer Bereich)und /4
sec
sbc #48
clc
ror
clc
ror
tay ;in y geht die x-Position
sec
mva var1 var2 ;holen der Bildschirmadresse -> var2
mva var1+1 var2+1
clc
@ lda var2 ;jetzt die y-Position auf die richtige Höhe stellen
adc #40
sta var2
lda var2+1
adc #0
sta var2+1
dex
bpl @- ;die y-Position steht in x - Addition von x Zeilen
@ dey ;die korrekte x-Position einstellen
lda (var2),y ;linken Rand checken
sta var8
iny
iny
lda (var2),y ;rechten Rand checken
sta var9
dey
dey
#if .byte var8=#0 .and .byte var9>#0 ;Position nach rechts anpassen
iny
#end
#if .byte var8>#0 .and .byte var9=#0 ;Position nach links anpassen
dey
#end
lda (var2),y ;2. Durchgang der Anpassung um letzte
sta var8 ;Fehler zu beseitigen
iny
iny
lda (var2),y
sta var9
dey
dey
#if .byte var8=#0 .and .byte var9>#0
iny
#end
#if .byte var8>#0 .and .byte var9=#0
dey
#end
lda (var2),y ;Korrektur der y-Position
sta var8 ;in var8 aktuelle BS-Position
sec
lda var2 ;eins drüber - bleibt wenn var2 zu tief
sbc #40
sta var2
lda var2+1
sbc #0
sta var2+1
lda (var2),y ;lade Bildschirminhalt eins drüber
sta var9 ;das geht in var9 rein
#if .byte var8>#0 .and .byte var9=#0 ;alte Position var2
clc ;wiederherstellen
lda var2
adc #40
sta var2
lda var2+1
adc #0
sta var2+1
#end
#if .byte var8=#0 .and .byte var9=#0 ;alte Position var2
clc ;eins runter
lda var2
adc #80
sta var2
lda var2+1
adc #0
sta var2+1
#end
lda (var2),y ;2. Durchgang der Anpassung um letzte
sta var8 ;Fehler zu beseitigen
sec
lda var2
sbc #40
sta var2
lda var2+1
sbc #0
sta var2+1
lda (var2),y
sta var9
#if .byte var8>#0 .and .byte var9=#0
clc
lda var2
adc #40
sta var2
lda var2+1
adc #0
sta var2+1
#end
#if .byte var8=#0 .and .byte var9=#0
clc
lda var2
adc #80
sta var2
lda var2+1
adc #0
sta var2+1
#end
#if .byte kollges=#1
sec
lda var2
sbc #80
sta var2
lda var2+1
sbc #0
sta var2+1
#end
#if .byte kollges=#8
sec
lda var2
sbc #80
sta var2
lda var2+1
sbc #0
sta var2+1
#end
;ab hier stimmt die Position des Items (meistens)
;in der Variable y für x-Position
;und in var2 für die y-Position
expl11
mva var2 tank1pos ;y-Position für Explosion1
mva var2+1 tank1pos+1
mva #96 audf1
mva #32 audc1
mva #222 audf2
mva #32 audc2
inc audc1
inc audc2
ldx #11
clc
@ mva expl1,x pr1,x
dex
bpl @-
jsr fuel.fuelex
inc audc1
inc audc2
tay
iny
expl22
mva tank1pos var2
mva tank1pos+1 var2+1
ldx #11
clc
@ mva expl2,x pr1,x
dex
bpl @-
inc audc1
mva #1 delay
jsr wartes
inc audc2
inc audc1
jsr fuel.fuelex
tay
iny
expl33
ldx #11
clc
@ mva expl3,x pr1,x
dex
bpl @-
mva tank1pos var2
mva tank1pos+1 var2+1
inc audc2
inc audc1
mva #1 delay
jsr wartes
jsr fuel.fuelex
inc audc1
inc audc2
tay
iny
expl44
ldx #11
clc
@ mva expl4,x pr1,x
dex
bpl @-
mva tank1pos var2
mva tank1pos+1 var2+1
inc audc1
inc audc2
mva #1 delay
jsr wartes
inc audc1
inc audc2
jsr fuel.fuelex
tay
iny
rts
.endp
.proc incfuelzaehler
inc fuelzaehleritem
lda fuelzaehler
tax
lda fuelzaehleritem
sta 31043,x
sta 32543,x
#if .byte fuelzaehleritem=#155
mva #151 fuelzaehleritem
inc fuelzaehler
#end
#if .byte fuelzaehler>#200
mva #0 fuelzaehler
#end
#if .byte fuelzaehler=#20
mva #52 color3
#end
#if .byte fuelzaehler>#34 .and .byte fuelzaehler<#200
;jmp main1
mva #0 fuelzaehler ;Fuel zuende Neustart
#end
mva #0 audc1
rts
.endp
.proc text
ldx #0
lda #52
jsr prte
inx
lda #45
jsr prte
inx
lda #54
jsr prte
inx
lda #31
jsr prte
inx
lda #52
jsr prte
inx
lda #49
jsr prte
inx
lda #0
jsr prte
inx
lda #54
jsr prte
inx
lda #50
jsr prte
inx
lda #0
jsr prte
inx
lda #51
jsr prte
inx
lda #47
jsr prte
inx
lda #50
jsr prte
inx
lda #42
jsr prte
inx
lda #50
jsr prte
inx
lda #53
jsr prte
inx
lda #0
jsr prte
inx
lda #55
jsr prte
inx
lda #34
jsr prte
inx
lda #32
jsr prte
inx
lda #34
jsr prte
inx
lda #34
jsr prte
inx
lda #0
jsr prte
inx
lda #51
jsr prte
inx
lda #45
jsr prte
inx
lda #54
jsr prte
inx
lda #45
jsr prte
inx
lda #52
jsr prte
inx
lda #0
jsr prte
inx
lda #51
jsr prte
inx
lda #52
jsr prte
inx
lda #50
jsr prte
inx
lda #44
jsr prte
inx
lda #45
jsr prte
inx
lda #47
jsr prte
inx
lda #48
jsr prte
inx
lda #0
jsr prte
ldx #0 ;Fuel
lda #46
jsr prte2
inx
lda #31
jsr prte2
inx
lda #45
jsr prte2
inx
lda #48
jsr prte2
ldx #10 ;Score
lda #53
jsr prte2
inx
lda #43
jsr prte2
inx
lda #50
jsr prte2
inx
lda #52
jsr prte2
inx
lda #45
jsr prte2
inx
lda #0
jsr prte2
inx
lda #160
jsr prte2
inx
lda #32
jsr prte2
inx
lda #32
jsr prte2
inx
lda #32
jsr prte2
ldx #23 ;Ships
lda #53
jsr prte2
inx
lda #47
jsr prte2
inx
lda #33
jsr prte2
inx
lda #51
jsr prte2
inx
lda #53
jsr prte2
inx
lda #0
jsr prte2
inx
lda #28
jsr prte2
inx
lda #29
jsr prte2
inx
lda #0
jsr prte2
inx
lda #28
jsr prte2
inx
lda #29
jsr prte2
inx
lda #0
jsr prte2
inx
lda #28
jsr prte2
inx
lda #29
jsr prte2
ldx #0
fuellauf
clc
lda fuelzaehleritem
@ jsr prte3
inx
cpx #36
bne @-
rts
prte sta 30923,x
sta 32423,x
rts
prte2 sta 31003,x
sta 32503,x
rts
prte3 sta 31043,x
sta 32543,x
rts
.endp
.proc pmvorbereiten
; Player vorbereiten und initialisieren
; Kollisionen: 4 = Grün 2 = Gelb
mva #10 yposp1
mva #120 xposp1
mva #42 yposm1
mva #0 xposm1
mva #94 yposm2
mva #49 xposm2
mva #0 tank1x
mva #0 tank1y
lda ramtop
sec
sbc #16
sta pmbase
clc
adc #3
sta miss1+1
sta miss2+1
sta miss3+1
sta miss4+1
adc #1
sta play1+1
adc #2
sta play3+1
adc #1
sta play4+1
lda #9
sta play4
lda #3
sta play3
mva #62 sdmctl
mva #56 pcolr0
mva #15 pcolr1
mva #119 pcolr2
mva #191 pcolr3
mva #1 gprior
mva #3 gractl
mva #1 sizep0
mva #1 sizep1
mva #1 sizep2
mva #0 sizem
mva #0 rechts
mva #2 hitclr
mva #48 blink
mva #40 p1pf
mva #8 hposm0
mva #8 hposm1
mva #8 hposm2
mva #8 hposm3
mva #1 yschuss1
mva #11 yschuss2
mva #22 yschuss3
mva #33 yschuss4
mva #0 schussi
mva <lands var6
mva >lands var6+1
mva #0 kollp0
ldy #255 ;Speicher Player 1 leeren
lda #0
sta play1
@ sta (play1),y
sta (play4),y
sta (play3),y
dey
bpl @-
clc
ldy yposp1 ;verticale Startpos. Player 1 + füllen
ldx #0
@ lda pm1,x
sta (play1),y
iny
inx
cpx #14
bne @-
rts
.end
.proc blinken
lda blink2
adc #59
sta blink2
#if .byte blink2>=#0 .and .byte blink2<#60
mva #0 blink
ldx #1
lda #0
ldy #2
mva #250 store1
jsr sound1
#end
#if .byte blink2>=#60 .and .byte blink2<#128
mva #14 blink
ldx #1
lda #0
ldy #2
mva #234 store1
jsr sound1
#end
#if .byte blink2>=#128 .and .byte blink2<=#192
mva #28 blink
ldx #1
lda #0
ldy #2
mva #218 store1
jsr sound1
#end
#if .byte blink2>=#192 .and .byte blink2<=#255
mva #42 blink
ldx #1
lda #0
ldy #2
mva #202 store1
jsr sound1
#end
rts
.endp
.proc schuesse
#if .byte yschuss1>#207
ldy yschuss1
dey
lda #0
sta (miss1),y
iny
sta (miss1),y
mva #8 hposm0
mva #1 hitclr
#end
#if .byte yschuss2>#207
ldy yschuss2
dey
lda #0
sta (miss1),y
iny
sta (miss1),y
mva #8 hposm1
mva #1 hitclr
#end
#if .byte yschuss3>#207
dey
lda #0
sta (miss1),y
iny
sta (miss1),y
mva #8 hposm2
mva #1 hitclr
#end
#if .byte yschuss4>#207
ldy yschuss4
dey
lda #0
sta (miss1),y
iny
sta (miss1),y
mva #1 hitclr
mva #8 hposm3
#end
rts
.endp
.proc kollmissile
#if .byte kollges=#4
mva #15 color3
sec
lda fuelzaehler
sbc #10
sta fuelzaehler
tax
mva #151 fuelzaehleritem
clc
lda fuelzaehleritem
@ sta 31043,x
sta 32543,x
inx
cpx #36
bne @-
jsr kollitem
mva #0 kollges
#end
#if .byte kollges=#8
jsr kollitem
lda #0
sta kollges
#end
#if .byte kollges=#1
jsr kollitem
lda #0
sta kollges
#end
rts
.endp
.proc variablensetzen
mva #>chr chbas ;HighByte Character Pointer auf $2000 setzen
mva #192 gprior ;GTIA Modus 3
mva #12 color3 ;Schriftfarbe
mva #220 color1 ;Gelb
mva #153 color0 ;Blau
;mva #52 color0 ;Rot
mva #180 color2 ; Grün
mva #0 color4 ;Hintergrundfarbe
lda #0 \ tax \ sta var3 \ sta var4 \ sta var6 \ sta var7 \ sta var6+1 \ sta feuer6
rts
.end
.proc dlist
.by 112,112,112,100
.by 30,75
:21 .by 36
:5 .by 4
.by 65
.wo dlist
.endp
.proc sound1
;x Register - Stimme
;Akkumulator - Distorsion
;y Register - Volumen
;Store2 - Frequenz
pha
txa
asl
tax
lda store1
sta audf1,x
sty store1
lda #0
sta audctl
lda #3
sta skctl
pla
asl
asl
asl
asl
clc
adc store1
sta audc1,x
rts
.endp
.proc sound2
;x Register - Stimme
;Akkumulator - Distorsion
;y Register - Volumen
;Store2 - Frequenz
pha
txa
asl
tax
lda store3
sta audf2,x
sty store2
lda #0
sta audctl
lda #3
sta skctl
pla
asl
asl
asl
asl
clc
adc store2
sta audc2,x
rts
.endp
.proc soundschuss
#if .byte sound12<#16 .and .byte sound12>#0
ldx #2
lda #1
ldy sound12
mva #2 store2
dec sound12
dec sound12
jsr sound2
clc
lda store3
adc #10
sta store3
#end
#if .byte sound12>=#15
mva #0 audc2
mva #0 audf2
ldx #0
lda #0
ldy #0
mva #170 store3
mva #0 store2
jsr sound2
mva #16 sound12
mva #170 store3
#end
rts
.end
run main
leider knackt mein Joystick so laut 😉
... heute habe ich es endlich hinbekommen!!
Die Explosion läuft animiert sauber durch während das Programm weiterscrollt... daran arbeite ich jetzt tatsächlich seit Wochen. Eine Idee war ja, daß die Explosion ständig im VBI animiert läuft und man beim Auslösen der Explosion einfach die ständig animierten Charakter auf das Item printet. So kann man letztlich. auch alles animieren wenn es die Zeit zuläßt. Ds habe ich prinzipiell umgesetzt, das Problem dabei ist natürlich, dass die Explosion nie vorbei ist und das explodierende Item quasi explodierend aus dem Bildschirm läuft... fand ich nicht so die beste Lösung. Darum habe ich ja alle 4 Explosionsphasen hintereinander laufen lassen mit kleiner Warteschleife, was dann ganz gut aussieht, was aber immer einen kleinen Ruckler erzeugt... auch blöd.
Gestern habe ich mir nochmal Caverns of Mars 1, 2 und Phobos angeschaut.. und tatsächlich war natürlich Caverns of Mars 1 noch relativ einfach gebaut... man sieht den enormen Fortschritt von CoM 2 und dann zu Phobos... Und hallo... in CoM 1 hat der Programmierer wohl ähnliche Probleme gehabt mit der Explosion, denn er macht es genauso und animiert sie ständig bis sie nach oben rausläuft... bei Phobos hat er es gelöst... dort läuft die Explosion sauber aber relativ langsam...
Mein Lösung nun: Mein Hauptprogramm habe ich mittlerweile relativ übersichtlich, da laufen ständig ein paar Subroutinenaufrufe .. also der Aufbau der letzten Reihe, Fein- und Grobscroll, Umschalten der Bidlschirme und Sound / Blinken. / Kollision. Der VBI läuft ja eh durch. Wenn nun eine Kollision stattfindet, dann ruft das Programm die entsprechende Subroutine auf, hier wird die genaue Position für die Explosion berechnet und korrigiert und dann laufen die 4 Phasen der Explosion hintereinander ab. Zwischen den einzelnen Phasen rufe ich nun einfach die Subroutinen für Feinscroll / Grobscroll / Umschalten und letzte Reihe jeweils auf (also das ganze Hauptprogramm) und das jedes Mal vor den einzelnen Explosionsphasen... zwischendurch muss ich nur noch die y-Position um 40 Einheiten korrigieren (weil er ja um eine Zeile scrollt) und das war es (fast). Das muss ich insgesamt 8 x machen, daher läuft die Explosion recht langsam durch, aber es funktioniert...
Was für ein tricky-Aufwand für diesen scheinbar simplen Effekt....... Morgen lade ich das mal als mov-Datei hoch! LG und gute Nacht Peter
P.s. Es gibt noch viel zu tun, aber so langsam muss ich mir Gedanken für mein nächstes Projekt machen... Ideen für ein schönes Spiel welcome!!
Hallo!
Schön zu sehen, dass Du Deine Probleme lösen kannst. Ich habe bei meiner Programmierung nun auch zum 3. Mal restrukturiert. Dafür lernt man aber immer mehr über den ATARI und durch den Lernfortschritt wird das Programm auch kürzer und somit optimierter. Wie im Interrupt-Thread vorgeschlagen, lasse ich in meiner Hauptschleife den Hintergrund am Anfang weiß setzten und zum Schluß wieder schwarz. Die Schleife wird immer direkt hinter einem VBI gestartet. Solange ich kein weiß auf dem Bildschirm sehe, ist die Hauptroutine schnell genug 🙂 Da es bei mir kein Scrolling gibt, habe ich da natürlich einen Vorteil.
Grüße Janko
Meine Projekte findest Du hier...
Das mit der Schleife ist gut… werde ich beim nächsten Projekt auch so machen… was programmierst du eigentlich, Janko?
Ich, ja... naja ist nur so ein Spiel wo Du eine Figur steuerst und Münzen einsammeln musst. Auf Zeichensatzgrafik basierend ohne Feinscrolling und so..
Aber ich habe z.B. einen horizontalen und vertikalen Textscroller im Menü, um diese Techniken zu testen. Dabei nutze ich die empfohlen Displaylist-Methode, wo ich die Displaylist nach 7 Schritte des Feinscrollings manipuliere und so keinen Speicher umkopieren muss. Funktioniert echt Sahne 🙂
Mein Wunsch ist es am Software-Wettbewerb teilzunehmen, auch wenn es nur der letzte Platz werden wird 😳 Deshalb veröffentliche ich auch nichts von meinem Spiel, weil dies leider untersagt ist. Ist aber auch noch viel zu programmieren. Mal sehen, ob ich es überhaupt fertig bekomme.
Grüße Janko
Meine Projekte findest Du hier...
Also ich würde wohl auch am Software-Wettbewerb teilnehmen, mein Spiel ist ja nicht fertig und "veröffentlicht", insofern sollte das kein Problem sein. Auch stammt der Code komplett von mir, wie man gut nachvollziehen kann... sollte die Kommision dennoch damit "Probleme" haben, dann wäre es auch kein Drama!
Ich werde mal bei Zeiten Sascha fragen, wie die das sehen... spätestens auf der NOMAM werde ich sie ja sehen. Ansonsten wäre ich wirklich sehr sehr interessiert an dem Scrollcode mit der D-List von dir, denn das will ich auf jeden Fall beim nächsten Mal umsetzen und müsste das Rad nicht komplett neu herleiten... 😉
Mein Scrollen verbrät halt richtig CPU Power ... das merkt man dann durchasu 😀
Hallo!
Ich habe einmal die von mir genutzte Routine separiert und als eigenes Programm hier eingefügt. Die Systemkonstanten müssen jedoch im selben Pfad liegen und inkludiert werden.
icl 'Systemkonstanten.asm'
; ########################################################################################################
; ### Speicherbereiche und Variabeln definieren
; Bildschirmspeicher ab $3000
org $3000
ScrMem01 .byte " "
ScrMem02 .byte " "
ScrMem03 .byte " "
ScrMem04 .byte " "
ScrMem05 .byte " "
ScrMem06 .byte " "
ScrMem07 .byte " "
ScrMem08 .byte " "
ScrMem09 .byte " "
ScrMem10 .byte " "
ScrMem11 .byte " "
ScrMem12 .byte " "
ScrMem13 .byte " "
ScrMem14 .byte " "
ScrMem15 .byte " "
ScrMem16 .byte " "
ScrMem17 .byte " "
ScrMem18 .byte " "
ScrMem19 .byte " "
ScrMem20 .byte " "
ScrMem21 .byte " "
ScrMem22 .byte " "
ScrMem23 .byte " "
ScrMem24 .byte " "
; # Displaylist ab $3400 definieren
org $3400
DPList .byte $70,$70,$70 ; 24 leere Scanzeilen (der normale obere Block)
.byte $42,<ScrMem01,>ScrMem01 ; Die oberen 2 Zeilen werden nicht gescrollt
.byte $42,<ScrMem02,>ScrMem02
VScrollStart .byte $62,<ScrMem03,>ScrMem03
.byte $62,<ScrMem04,>ScrMem04
.byte $62,<ScrMem05,>ScrMem05
.byte $62,<ScrMem06,>ScrMem06
.byte $62,<ScrMem07,>ScrMem07
.byte $62,<ScrMem08,>ScrMem08
.byte $62,<ScrMem09,>ScrMem09
.byte $62,<ScrMem10,>ScrMem10
.byte $62,<ScrMem11,>ScrMem11
.byte $62,<ScrMem12,>ScrMem12
.byte $62,<ScrMem13,>ScrMem13
.byte $62,<ScrMem14,>ScrMem14
.byte $62,<ScrMem15,>ScrMem15
.byte $62,<ScrMem16,>ScrMem16
.byte $62,<ScrMem17,>ScrMem17
.byte $62,<ScrMem18,>ScrMem18
.byte $62,<ScrMem19,>ScrMem19
.byte $62,<ScrMem20,>ScrMem20
.byte $62,<ScrMem21,>ScrMem21
.byte $42,<ScrMem22,>ScrMem22
.byte $42,<ScrMem23,>ScrMem23 ; Die unteren 2 Zeilen werden ebenfalls
.byte $42,<ScrMem24,>ScrMem24 ; nicht gescrollt
.byte $41,<DPList,>DPList ; JVB, und die Displaylist wieder starten
; # Scrollschema, um weniger berechnen zu müssen
DPScroll .word ScrMem03, ScrMem04, ScrMem05, ScrMem06, ScrMem07
.word ScrMem08, ScrMem09, ScrMem10, ScrMem11, ScrMem12
.word ScrMem13, ScrMem14, ScrMem15, ScrMem16, ScrMem17
.word ScrMem18, ScrMem19, ScrMem20, ScrMem21, ScrMem22
.word ScrMem03, ScrMem04, ScrMem05, ScrMem06, ScrMem07
.word ScrMem08, ScrMem09, ScrMem10, ScrMem11, ScrMem12
.word ScrMem13, ScrMem14, ScrMem15, ScrMem16, ScrMem17
.word ScrMem18, ScrMem19, ScrMem20, ScrMem21
VScrollFine .byte $00 ; Finescrolling hier festhalten
VScrollPos .byte $02 ; Position des Zeigers für DPScroll
VScrollNext .byte $00 ; Temporäre-Variable
StoryPos .word Story ; Zeiger innerhalb des Textes
; $FE = Zeilenende oder 40 Zeichen ausgeben
; $FF = Text von vorne ausgeben
; 0123456789012345678901234567890123456789
Story .byte "Hier kommt die Textausgabe:",$FE
.byte $FE
.byte "Eine volle 40er Zeile benoetigt kein $FE"
.byte "am Ende",$FE
.byte $FE,$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte $FE,$FE,$FE,$FE,$FE,$FF
; ############################################################################
; # VSync
; #
.proc WaitVSync
lda RTCLOK+2
Loop cmp RTCLOK+2
beq Loop
rts
.end
; ########################################################################################################
; ### VBI - Routine zum Scrollen
.proc VBI
jsr VScroller
jmp XITVBV
; ### Unterroutinen im VBI
VScroller ; ######## Vertikaler Freinscroller im mittleren Titelbereich ########
inc VScrollFine
lda VScrollFine
cmp #$08
beq @+ ; Wenn Feinscolling bei 8 dann Grobscrolling
sta VSCROL
rts
@ ; ######## Vertikales Grobscrolling durch Displaylist-Manipulation
lda #$00 ; Feinscrolling auf 0 setzen
sta VScrollFine
sta VSCROL
ldx VScrollPos ; 20 Zeilen werden gescrollt
cpx #$28 ; Danach wieder auf 0 setzen
bcc @+
ldx #$00
stx VScrollPos
@ txa ; Damit X und Y nicht von 0 zählen
clc ; müssen, wird er Endwert für X
adc #$28 ; berechnet. Nun kann man direkt
sta VScrollNext ; hiermit vergleichen
ldy #$00 ; Y auf Null setzen, jedoch zählt
; Y immer drei Schritte hoch
@ iny ; pro Durchgang (Befehl, LOMEM, HIMEM)
lda DPScroll,x ; LO-Wert holen
sta VScrollStart,y ; und in der Displaylist setzen
inx
iny
lda DPScroll,x ; HI-Wert holen
sta VScrollStart,y ; und in der Displaylist setzen
iny
inx
cpx VScrollNext ; Alle Zeilen abgearbeitet?
bcc @-
; -- Ab hier kommt die Textausgabe
; -- Die natürlich vereinfacht werden kann
; -- Wichtig ist, dass der Text ab der Adresse
; -- Ausgabe1 bzw. Ausgabe2 augegeben wird
dex ; Zurück zur letzten Zeile
dex
lda DPScroll,x ; LO und HI müssen für die
sta Ausgabe1+1 ; Ausgabe der letzten Zeile
sta Ausgabe2+1 ; zwei Mal im Programmcode
inx ; übertragen werden
lda DPScroll,x ; Page 0 ist dann nicht
sta Ausgabe1+2 ; notwendig
sta Ausgabe2+2
inc VScrollPos ; Die Position fürs nächste scrollen
inc VScrollPos ; setzen
ZeileAusgeben lda StoryPos ; Nun den Zeiger innerhalb des
sta Textzeile+1 ; Textes setzen
lda StoryPos+1 ; und wieder ohne Page 0 direkt
sta Textzeile+2 ; im Programmcode speichern
ldx #$00
Textzeile lda $ffff,x ; Die Adresse zur Ausgabe wird manipuliert
cmp #$FE ; $FE signalisiert, dass die restlichen Zeichen
beq Zeilenende ; Leerzeichen sein sollen.
cmp #$FF ; $FF signalisiert, dass der Text von vorne
beq Textende ; ausgegeben werden soll.
Ausgabe1 sta $ffff,x
inx
cpx #$28 ; max. 40 Zeichen ausgeben
bcc Textzeile
stx TextNext+1 ; X-Zähler merken
Weiter clc
lda StoryPos
TextNext adc #$ff ; Die X gemachten Schritte werden nun auf den
sta StoryPos ; Gesamtzeiger addiert
lda StoryPos+1
adc #$00
sta StoryPos+1
rts ; Fertig mit dem Grobscrolling und der Zeilenausgabe
Zeilenende inx ; Rest Leerzeichen ausgeben
stx TextNext+1 ; X+1 abspeichern
dex ; Nun X wieder einen zurück, um die Ausgabe richtig
; zu starten
lda #" " ; restlichen Leerzeichen ausgeben
Ausgabe2 sta $ffff,x
inx
cpx #$28 ; bis max. 40 Stück
bcc Ausgabe2
jmp Weiter
Textende lda #<Story ; Text soll von vorne ausgegeben werden
sta StoryPos ; Hierfür den Zeiger wieder auf den
lda #>Story ; Anfang des Textes setzen
sta StoryPos+1
jmp ZeileAusgeben
.end
; ########################################################################################################
; ### Hauptprogramm
.proc main
lda #<DPList ; Displaylist laden
sta SDLSTL
lda #>DPList
sta SDLSTL+1
jsr WaitVSync
ldy #<VBI ; VBI für einrichten
ldx #>VBI
lda #7
jsr SETVBV
jsr WaitVSync
Loop jmp Loop
.end
; ########################################################################################################
run main
Ich hoffe, dass der Quellcode nachvollziehbar ist. Sicherlich kann man hier noch optimieren.
Grüße Janko
Meine Projekte findest Du hier...
... habs gleich mal ausprobiert... sehr geil!! Läuft echt flüssig! Ich schau mir den Code noch ganz genau an, vielleicht kann ich das etwas umbauen und bei mir noch nutzen.... Vielen Dankfür den schönen Code!! LG Peter
... nochmal zum Grobscrollcode:
Der Graphikbildschirm hat im Textmodus 24 Zeilen a 40. Jede Zeile in der Displaylist bekommt also eine 2 eingeschrieben (die ersten 24 Scanlines bleiben leer). Die erste Zeile hat dabei nicht den Wert 2 sondern 66 (64+2) - wobei die 64 einen Adressbefehl darstellt - nämlich den des Bildschirmanfanges. Es folgen dann die 23 nächsten Zeilen mit dem Wert 2 und danach kommt noch der Sprungbefehl mit Adresse des Displaylistanfanges.
Nun möchten wir folgendes machen: In jede Zeile schreibe ich statt einer 2 eine 66 (alles dezimal) rein mit der jeweiligen um eine Zeile höheren Adresse für den Bildschirm: 66 64 156 (40000) 66 104 156 (40040) 66 144 156 (40080) 66 184 156 66 224 156 .......... usw am Ende wieder der Sprungbefehl für den Start der Displaylist.
Als nächstes (mein Grobscroll) kopiere ich einfach die Displaylist um - verschiebe also alle Zeilen um eins nach oben: 66 104 156 66 144 156 66 184 156 66 224 156 66 08 157 ..... 66 64 156 Sprungbefehl Displaylistanfang
die letzte Zeile vor dem Sprungbefehl müsste dann wohl immer die vorherige erste sein. Damit bekomme ich ein fortlaufendes Grobscroll des gesamten Bildschirmes. Will ich jetzt einen Shooter damit machen, überschreibe ich einfach die komplette erste Zeile der Displaylist mit den neuen Landschaftsdaten (meine "letzte Reihe") - anschließend wird die erste Reihe durch Umsortierung der Displaylist letzte Reihe. Theoretisch könnte ich auch ganz einfach 24 verschiedene Displaylist mit entsprechend versetzten Zeilen vorbereiten und dann einfach nur jeweils von Displaylist 1 zu 2 zu 3 zu .... zu 24 umschalten. Die Displaylist wird dann noch so aufgebaut, daß der entsprechende Graphicmodus plus Feinscroll mit drin ist, der Grobscroll wird entsprechend immer einmal nach 7 Feinscrollaktionen durchgeführt.
So habe ich die Theorie verstanden.... das möchte ich demnächst mal umsetzen. Habe ich das korrekt verstanden?? Liebe Grüße Peter
Hallo Peter!
Deine Idee direkt umzukopieren, also ohne eine Tabelle, macht die Routine noch etwas smarter.
Hier ein Update:
icl 'Systemkonstanten.asm'
; ########################################################################################################
; ### Speicherbereiche und Variabeln definieren
; Bildschirmspeicher ab $3000
org $3000
ScrMem01 .byte " "
ScrMem02 .byte " "
ScrMem03 .byte " "
ScrMem04 .byte " "
ScrMem05 .byte " "
ScrMem06 .byte " "
ScrMem07 .byte " "
ScrMem08 .byte " "
ScrMem09 .byte " "
ScrMem10 .byte " "
ScrMem11 .byte " "
ScrMem12 .byte " "
ScrMem13 .byte " "
ScrMem14 .byte " "
ScrMem15 .byte " "
ScrMem16 .byte " "
ScrMem17 .byte " "
ScrMem18 .byte " "
ScrMem19 .byte " "
ScrMem20 .byte " "
ScrMem21 .byte " "
ScrMem22 .byte " "
ScrMem23 .byte " "
ScrMem24 .byte " "
; # Displaylist ab $3400 definieren
org $3400
DPList .byte $70,$70,$70 ; 24 leere Scanzeilen (der normale obere Block)
.byte $42,<ScrMem01,>ScrMem01 ; Die oberen 2 Zeilen werden nicht gescrollt
.byte $42,<ScrMem02,>ScrMem02
VScrollStart .byte $62,<ScrMem03,>ScrMem03
.byte $62,<ScrMem04,>ScrMem04
.byte $62,<ScrMem05,>ScrMem05
.byte $62,<ScrMem06,>ScrMem06
.byte $62,<ScrMem07,>ScrMem07
.byte $62,<ScrMem08,>ScrMem08
.byte $62,<ScrMem09,>ScrMem09
.byte $62,<ScrMem10,>ScrMem10
.byte $62,<ScrMem11,>ScrMem11
.byte $62,<ScrMem12,>ScrMem12
.byte $62,<ScrMem13,>ScrMem13
.byte $62,<ScrMem14,>ScrMem14
.byte $62,<ScrMem15,>ScrMem15
.byte $62,<ScrMem16,>ScrMem16
.byte $62,<ScrMem17,>ScrMem17
.byte $62,<ScrMem18,>ScrMem18
.byte $62,<ScrMem19,>ScrMem19
.byte $62,<ScrMem20,>ScrMem20
.byte $62,<ScrMem21,>ScrMem21
.byte $42,<ScrMem22,>ScrMem22
.byte $42,<ScrMem23,>ScrMem23 ; Die unteren 2 Zeilen werden ebenfalls
.byte $42,<ScrMem24,>ScrMem24 ; nicht gescrollt
.byte $41,<DPList,>DPList ; JVB, und die Displaylist wieder starten
; # Scrollschema, um weniger berechnen zu müssen
VScrollFine .byte $00 ; Finescrolling hier festhalten
VScrollLast .byte 57 ; Anzahl wieviele Schritte X gehen muss = (20*3)-3
StoryPos .word Story ; Zeiger innerhalb des Textes
; $FE = Zeilenende oder 40 Zeichen ausgeben
; $FF = Text von vorne ausgeben
; 0123456789012345678901234567890123456789
Story .byte "Hier kommt die Textausgabe:",$FE
.byte $FE
.byte "Eine volle 40er Zeile benoetigt kein $FE"
.byte "am Ende",$FE
.byte $FE,$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte " # #",$FE
.byte $FE,$FE,$FE,$FE,$FE,$FF
; ############################################################################
; # VSync
; #
.proc WaitVSync
lda RTCLOK+2
Loop cmp RTCLOK+2
beq Loop
rts
.end
; ########################################################################################################
; ### VBI - Routine zum Scrollen
.proc VBI
jsr VScroller
jmp XITVBV
; ### Unterroutinen im VBI
VScroller ; ######## Vertikaler Freinscroller im mittleren Titelbereich ########
inc VScrollFine
lda VScrollFine
cmp #$08
beq @+ ; Wenn Feinscolling bei 8 dann Grobscrolling
sta VSCROL
rts
@ ; ######## Vertikales Grobscrolling durch Displaylist-Manipulation
lda #$00 ; Feinscrolling auf 0 setzen
sta VScrollFine
sta VSCROL
lda VScrollStart+1 ; Die Zeile die oben verschwindet
sta Ausgabe1+1 ; und unten mit neuen Text erscheint
sta Ausgabe2+1 ; muss zwischen gespeichert werden
lda VScrollStart+2 ; Hier noch das Hi-Byte
sta Ausgabe1+2
sta Ausgabe2+2
ldx #$00 ; Nun alle Zeilen umkopieren
@ lda VScrollStart+4,x ; aber nur die Angabe der
sta VScrollStart+1,x ; Speicheradresse
lda VScrollStart+5,x
sta VScrollStart+2,x
inx ; 3 Schritte weiter
inx
inx
cpx VScrollLast ; Alle Zeilen abgearbeitet?
bcc @-
lda Ausgabe1+1 ; Nun die gemerkte 1. Zeile
sta VScrollStart+1,x ; unten noch anfügen
lda Ausgabe1+2
sta VScrollStart+2,x
; -- Ab hier kommt die Textausgabe
; -- Die natürlich vereinfacht werden kann
; -- Wichtig ist, dass der Text ab der Adresse
; -- Ausgabe1 bzw. Ausgabe2 augegeben wird
ZeileAusgeben lda StoryPos ; Nun den Zeiger innerhalb des
sta Textzeile+1 ; Textes setzen
lda StoryPos+1 ; und wieder ohne Page 0 direkt
sta Textzeile+2 ; im Programmcode speichern
ldx #$00
Textzeile lda $ffff,x ; Die Adresse zur Ausgabe wird manipuliert
cmp #$FE ; $FE signalisiert, dass die restlichen Zeichen
beq Zeilenende ; Leerzeichen sein sollen.
cmp #$FF ; $FF signalisiert, dass der Text von vorne
beq Textende ; ausgegeben werden soll.
Ausgabe1 sta $ffff,x
inx
cpx #$28 ; max. 40 Zeichen ausgeben
bcc Textzeile
stx TextNext+1 ; X-Zähler merken
Weiter clc
lda StoryPos
TextNext adc #$ff ; Die X gemachten Schritte werden nun auf den
sta StoryPos ; Gesamtzeiger addiert
lda StoryPos+1
adc #$00
sta StoryPos+1
rts ; Fertig mit dem Grobscrolling und der Zeilenausgabe
Zeilenende inx ; Rest Leerzeichen ausgeben
stx TextNext+1 ; X+1 abspeichern
dex ; Nun X wieder einen zurück, um die Ausgabe richtig
; zu starten
lda #" " ; restlichen Leerzeichen ausgeben
Ausgabe2 sta $ffff,x
inx
cpx #$28 ; bis max. 40 Stück
bcc Ausgabe2
jmp Weiter
Textende lda #<Story ; Text soll von vorne ausgegeben werden
sta StoryPos ; Hierfür den Zeiger wieder auf den
lda #>Story ; Anfang des Textes setzen
sta StoryPos+1
jmp ZeileAusgeben
.end
; ########################################################################################################
; ### Hauptprogramm
.proc main
lda #<DPList ; Displaylist laden
sta SDLSTL
lda #>DPList
sta SDLSTL+1
jsr WaitVSync
ldy #<VBI ; VBI für die Musik einrichten
ldx #>VBI
lda #7
jsr SETVBV
jsr WaitVSync
Loop jmp Loop
.end
; ########################################################################################################
Grüße Janko
Meine Projekte findest Du hier...
Prodehl schrieb: So habe ich die Theorie verstanden.... das möchte ich demnächst mal umsetzen. Habe ich das korrekt verstanden??
So hatte ich es in meinem Posting gemeint und so habe hinterher auch Lars verstanden (der im Gegensatz zu mir praktische Erfahrung darin hat).
Weiterhin viel Erfolg
Die letzten Tage habe ich die Schranken programmiert. Eine Schranke war recht einfach zu machen und kostet mich auch nur einen zusätzlichen Charakter in der schon recht vollen Tabelle. Dieser Charakter wird dann im VBI mit 8 einfachen kurzen Befehlen ständig verändert und im Hauptprogramm wird das dann zusätzlich per Random gemischt und ein - / ausgeschaltet. Diese Schranke kann ich beliebig dick machen. Ich habe es als Sonderitem in den Aufbau der Landschaft integriert und kann die Schranke jetzt also irgendwo frei platzieren. Die 2. Schranke ist auch fertig. Dies ist eine Laufschranke jeweils von rechts nach links und umgekehrt, sowie in Kombination ... das war jetzt zwar nicht schwerer zu programmieren, braucht aber etliche Programmschritte, weil ich es mit ROL und ROR mache, dabei 14 Charakter benötige und jedes Charakter ja 8 Bits hat. Der Rechner macht also bei dieser Schranke ständig 112 Befehlszyklen, was ich leider nicht mehr ohne Ruckeln so einfach in den VBI unterbekomme. Ich habe es also ins Hauptprogramm integriert und wenn alles läuft... also Schranke Scroll usw. ruckelt es ein wenig... das Problem habe ich noch nicht gelöst und werde es wohl so hinnehmen. Man sieht auf jeden Fall, daß der Rechner mit dem Gesamtkonstrukt so langsam hinsichtlich der Kapazität an der Grenze ist... zumindest so wie ich es aufgebaut habe. Das Folgeprogramm werde ich anders konstruieren müssen... Nun baue ich noch viel Landschaft und dann das Endlevel, dann müssen noch die Kollisionsabfragen für das Raumschiff geschaltet werden, Bonusschiffe für erreichten Score, die ganzen kleinen Fehler noch raus und fertig bin ich mit dem Projekt! Hier noch eine kleine Demo mit den beiden Schranken... Liebe Grüße und ein schönes WE Peter
... jetzt habe ich mal in meiner Feinscroll-Routine mit vcount "gespielt" und siehe da - wenn man das timing richtig setzt ist das unangenehme Ruckeln weg. Und plötzlich habe ich auch wieder Optionen im VBI. Ich kann jetzt die Laufschranke in den VBI integrieren und es läuft super flüssig! Und da geht noch viel mehr Code rein... cool!!
Das timing läuft natürlich anders auf 50 Hz (PAL) als auf 60 Hz ... ich frage das jetzt beim Programmstart durch das Register PAL ab und ändere entsprechend den Wert für das timing. Jetzt läuft das Programm flüssig bei 50 und 60 Hz!
Prodehl schrieb: Das timing läuft natürlich anders auf 50 Hz (PAL) als auf 60 Hz ... ich frage das jetzt beim Programmstart durch das Register PAL ab und ändere entsprechend den Wert für das timing. Jetzt läuft das Programm flüssig bei 50 und 60 Hz!
Wenn Du das Timing wirklich korrekt auch auf umgebauten Rechnern haben möchtest (PAL ANTIC im NTSC ATARI), solltest Du nicht über das PAL Register gehen. Man sollte dann in einer kleinen Routine zählen, wie viele VCOUNTs möglich sind. 60 Hz Maschinen schaffen weniger, als 50 Hz Maschinen. Mindestens bis 155 sollte es gehen, dann hast Du ein Gerät mit 50 Hz. Ist der höchste VCOUNT Wert kleiner, hast Du ein 60 Hz Gerät.
Über das PAL Register weiß man aber zuverlässig, ob die Farben angepasst werden müssen.
PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo
Hallo!
Das mit dem Zählen ist ein super Hinweis. Habe bis jetzt nur das PAL-Register abgefragt gehabt.
Würdest Du auch so zählen?
@ lda VCOUNT ; Anzahl der VCounts zählen
cmp VCOUNT ; Bei über 155 Schritten
beq @- ; hat man 50Hz, darunter
bcc @- ; hat man 60Hz
cmp #$9b
bcs IS_50hz
IS_60Hz lda #$01
jmp @+
IS_50hz lda #$00
@ sta is60Hz
Grüße Janko
Edit: Hab den Code noch einmal geändert gehabt
Meine Projekte findest Du hier...
Das sieht auf den ersten Blick gut aus.
EDIT: Auf den zweiten aber dann doch wohl nicht.
Nutze am besten eine temporäre Variable zum zählen und vor allem setze am Anfang VCOUNT auf 0. So mache ich das meist:
;50Hz or 60 Hz?
mva #0 vcount
@ lda vcount
beq w
sta temp
jmp @-
w
lda temp
cmp #$9b
bmi ntsc
;PAL
mva #0 sixtyhz
rts
ntsc
mva #1 sixtyhz
rts
PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo
Guten Morgen in die Gemeinde, ich habe jetzt alle Schranken und Hindernisse fertig und bin dabei die Landschaft zu erweitern. Ich würde mal sagen, daß ich jetzt insgesamt die Hälfte der Landschaft kreiert habe. Mit dem ganzen Programmcode bin ich jetzt bei ca. 24kB ... da scheint noch etwas Luft, aber ich muss jetzt noch ein paar Sachen ändern. Ich starte mit dem Code jetzt nicht bei $2000, sondern bei $400. Auch musste ich ein paar Variablen umdeklarieren, da der Code da sonst reingrätscht. Ich habe noch freie Slots unterhalb $400 gefunden und benutzt. Ein etwas größerer Part wird noch die Displaylist samt Bildschirm sein. Das fängt bei mir ja bei $7530 (30000) an, entweder schiebe ich das nach ganz vorne - also direkt hinter die Charakter, oder soweit nach hinten wie es geht - da brauche ich ca. 2kB an Platz. Jetzt ist es nämlich so, wenn mein Programm in die $7530 Speicherbereiche reingeht, kommt es zu einem kompletten fatalen Absturz - was ja logisch ist. Vielleicht lege ich die DL und den Bildschirm etwa bei 47000 hin, dann habe ich noch massig Platz für das Programm. Bei meinem nächsten Projekt werde ich vorher mir ganz genau Gedanken machen, wie ich den Speicher optimal nutze... LG Peter
Hallo!
Kann man "Return to Phobos" überhaupt dann noch via eines DOS starten, wenn Du den Bereich <$2000 nutzt? Das DOS liegt normal an dieser Stelle. Auch einige Speeder haben sich in dem Bereich einquartiert.
Ich habe mein Programm so geschrieben, dass man mit "Escape" ins DOS zurück kehrt 🙂 Habe dafür mein Programm testweise auf eine ATR geschrieben mit DOS 2.5 und über das DOS geladen.
Grüße Janko
Meine Projekte findest Du hier...
Laden von Dos … daran habe ich gar nicht gedacht… das werde ich entsprechend noch anpassen, damit man das Spiel normal von Diskette laden kann!
Jetzt habe ich das Programm etwas umgestellt ... Programmstart jetzt bei 2048 ($800), Bildschirmausgabe statt 30000 jetzt bei 41000 ($A028). Ich weiß gar nicht, warum ich bei 30000 den Bildschirmstart gesetzt habe... dadurch habe ich für das ganze Programm 15 kB mehr zur Verfügung.... Da passt noch Landschaft rein, Programmcode und Sound...
Prodehl schrieb: Programmstart jetzt bei 2048 ($800)
Wenn du es aus dem DOS starten und ggf. wieder dorthin zurückkehren willst, ist das immer noc hviel zu niedrig. Du solltest dann nicht unter $2000 beginnen.
Schaue Dir mal das uDOS von @Dietrich an. Dort hast Du zwar keine DOS Oberfläche, aber es bietet grundlegende Funktionen, die so ein Spiel benötigt und bietet möglichst geringe Speichernutzung. Habe gerade nicht den genauen Punkt im Kopf... So etwa ab $940 kann man da ein Programm starten lassen.
PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo
Ich habe mich in der Tat noch nicht damit beschäftigt und lediglich am Anfang mal ausprobiert, ob sich das Programm generell auf meinem Atari 130 XE starten lässt. Ich programmiere ja unter Eclipse / MADS und da wird dann eine xex-Datei generiert. Die läßt sich via Fujinet einfach laden. Wie aber bekomme. ich das auf eine normale 5 1/2 Zoll Diskette, wo das startbare Programm ist und wo dann das Programm einfach gestartet wird. Ins DOS zurück müsste man nicht... das ging doch bei den ganzen Spielen früher in der Regel auch nicht!
Mit dem Disk-Explorer vom Altirra in eine atr schieben und dann via SIO2PC auf eine physikalische Disk kopieren. Oder mit MakeATR.
lieben Dank ersteinmal... gibt es da auch was für Mac??
also das uDOS habe ich nirgends gefunden 🙈
Meine Projekte findest Du hier...
Lieben Dank!! Brauche ich denn überhaupt das DOS?? Ich muss doch nur eine startfähige Diskette mit meinem Programm erstellen (wie das geht weiß ich noch nicht) - wo dann am Anfang irgendwo steht, wohin in den Speicher das Programmgeladen wird und wo dann wohl auch der Start erfolgen soll...?!
Hallo!
Es kommt ein wenig darauf an, was Du vor hast. Eine Weitergabe ist sicherlich einfacher, wenn man es mit anderen Programmen von einem DOS heraus aufrufen kann.
Wenn Du nach hinten heraus noch 15kb frei hast, spricht doch nichts gegen eine kompatible Start-Adresse?
Grüße Janko
Meine Projekte findest Du hier...
Die übrigen 15 kB sind ja mit Startadresse C00 gerechnet und ich habe für den gesamten geschätzten Rest der Landschaft bereits Platzhalter drin - d.h. ich brauche noch ein paar KB für Sound und Code... wenn alles fein ist, dann werde ich den Programmstart so gestalten, daß ein DOS bequem reinpasst! Liebe Grüße
Prodehl schrieb: Brauche ich denn überhaupt das DOS?? Ich muss doch nur eine startfähige Diskette mit meinem Programm erstellen
Das ist im Prinzip korrekt. Für eine Bootdiskette benötigst du nur im ersten Sektor einen kleinen Header von sechs Byte, der dem Atari sagt, wieviele Sektoren er booten soll, wohin im RAM die geladen werden sollen und wo die (endgültige) Startadresse liegt. "endgültig" weil nach dem Bootvorgang automatisch an Ladeadresse+6 zur Initialisierung gesprungen wird. Nur wenn das Init mittels RTS beendet wird, erfolgt der Sprung zur Startadresse aus dem Header. Das ist ein bisschen wie beim DOS mit RUNAD $2e0 und INITAD $2e2.
ABER: Häufig wird ein Programm nicht an ein Stück assembliert, sondern ist verteilt auf verschiedene Bereiche im RAM, die du vorher durch org-Befehle definiert hast. Das DOS ist in der Lage, diese Blöcke aus einer XEX-Datei an die jeweils richtige Stelle zu laden. Hast du aber eine Bootdiskette musst du dich mit einem eigenen Lader darum komplett selber kümmern, dass die Daten aus den Sektoren an die richtigen Stellen im RAM kommen. Und vorher musst du aus deiner XEX-Datei diese Blöcke rausschneiden und auf der Bootdiskette entsprechend verteilen.
Deshalb ist echt vorteilhaft, ein DOS zu verwenden.
Mit der Option f kann man mit MADS ein komplett hintereinander assembliertes File erzeugen. So geht auch direkt eine eigene Bootdisk. Das habe ich bei der Diskversion von runfast so gemacht. Das komplette atr ist mit MADS erstellt. Am Sonntag kann ich da eventuell etwas source code zu liefern.
Aber ein "normales" com File (oder auch xex) ist letzten Endes einfacher für die Leute zu handhaben.
PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo
das hört sich interessant an!! Bin gespannt auf Sonntag!! Danke schon mal an alle! LG Peter
Als kleines DOS, nebst minimalistischer Oberfläche bietet sich auch LiteDOS an: http://mr-atari.com/Mr.Atari/LiteDOS/ da kann man seine Programme ab $1000 starten lassen.
Sorry, hatte auch heute ordentlich zu tun. Aber jetzt hatte ich mal ein paar Minuten Zeit und hier der versprochene Source Code:
/*
16 bars boot disc based on 510b+ from nyd2022
*/
; @com.wudsn.ide.asm.hardware=ATARI8BIT
; @com.wudsn.ide.asm.outputfileextension=.atr
opt l-
;---- ATARI addresses
hposp0 = $D000
hposp1 = $D001
hposp2 = $D002
hposp3 = $D003
sizep0 = $D008
sizep1 = $D009
sizep2 = $D00A
sizep3 = $D00B
trig0 = $D010
trig1 = $D011
colpm0 = $D012
colpm1 = $D013
colpm2 = $D014
colpm3 = $D015
colbak = $D01A
color2 = $D018
gtictl = $D01B
pmcntl = $D01D
consol = $D01F
skctl = $D20F
dmactl = $D400
pmbase = $D407
wsync = $D40A
nmien = $D40E
;---
opt l+
compileto equ $2000
sectors equ ((fin-compileto)/128)+1
opt f+ ;Activate fill mode
opt h- ;no headers
;;; ATR disk header
.word $0296, $8, $80
:10 .he 00
org compileto
;--------------------------- boot init
.proc boot
.he 00 ;always 0
dta b(sectors) ;how many sctors to load
.wo boot ;load address
.wo init ;init address (seems not to be used)
jmp start
; mva #$24 710
.endp
;--------------------------- boot init end
.proc init
;you can start an intro here
rts
.endp
;---------------------------
.zpvar .byte ct,wt,mx,shape,rega,regx,posp1,posp0
ri equ $a0 ;needs 16 bytes
pos equ $b0 ;needs 16 bytes
col equ $c0 ;needs 16 bytes
pmg equ $2000
p0 equ $2000+$400
p1 equ $2000+$500
p2 equ $2000+$600
p3 equ $2000+$700
;---------------------
.local DL
.he 70 80
:12 .he 70 ;have to use it on boot disc again
; .ds 96 ;mega cheat :) 12 times $70 or just 96 times 0 if area is clear
.he 42
.wo txt
.he 41
.wo DL
txt dta d'NYD 2022',d' 16bars_510b+ '*,d' by PPs '
.endl
;---------------------
.local dli
sta rega
stx regx
mva posp0 hposp0
mva posp1 hposp1
dec posp0
inc posp1
mva #%00111001 dmactl ;set screen width (32b,dma,players)
sta wsync
mva #$21 gtictl
;--- additional pm
rol ;$42 red
sta colpm2
rol ;$84 blue
sta colpm3
;--- additional pm
;stripes
ldx #0
@ lda start.area,x
sta colbak
and #$7f
sta colpm0
sta colpm1
lda shape
ror
ror
ror
sta color2
sta wsync
inx
cpx #210
bne @-
lda #0
sta colpm0
sta colpm1
ldx regx
lda rega
rti
.endl
;---------------------
.proc start
.proc main
jsr clear_area
mwa #DL 560
sta pmbase ;-> high byte is $20 ;)
sta 513 ;-> high of DLI is $20, too ;)
mva <dli 512
;--- set colors ;.he 00 10 20 30 40 50 60 70 80 90 a0 b0 c0 d0 e0 f0
.local setcol
ldx #15
lx lda #$f0
sta col,x
sub #$10
sta lx+1
dex
bpl lx
.endl
;---
stx shape ;$ff
stx wt
stx ct
;---------------------
.local set_pm
txa ;x and a @$ff
@ sta p0,x
sta p1,x
dex
bne @-
;--- additional pm
ldx #7
; lda #$f0
@ sta p2+113,x
sta p3+113,x
dex
bpl @-
mva #$70 posp0
sta posp1
mva #$40 hposp2
mva #$a0 hposp3
;--- additional pm
.endl
;---------------------
mva #3 sizep0
sta sizep1
;--- additional pm
sta sizep2
sta sizep3
;--- additional pm
sta pmcntl ;enable players and missiles
mva #$c0 nmien ;DLI + VBI on
lp
;Test ob Ende
/* lda trig0
beq @+
lda trig1
beq @+
lda skctl
and #$04
beq @+
lda consol
and #1
bne noend
@ jmp $e477 ;cold reset
noend
*/ dec wt
lda wt
bpl out
mva #2 wt
sta 77
dec ct
out
;---------------------
.local stripes
;run thru the 16 stripes
ldx #15
stx mx
lp_str
lda ri,x
beq hoch
runter
lda pos,x
cmp #196
beq change_up
;runter geht noch
inc pos,x
lda pos,x
tay
jsr copyshape
jmp next
change_up ;up again
ldx mx
dec ri,x
hoch
lda pos,x
beq change_down
;hoch geht noch
dec pos,x
lda pos,x
tay
jsr copyshape
jmp next
change_down ;down again
ldx mx
inc ri,x
jmp runter
next
dec mx
ldx mx
bpl lp_str
.endl
;---------------------
lda ct
bne lp
dec ct ;set back 2 $ff
jsr chg_shape
jmp lp
.endp
;---------------------
.local copyshape
;first
lda #0
sta area,y
;1
lda col,x
sta area+1,y
sta area+12,y
;2
lda col,x
ora #2
sta area+2,y
sta area+11,y
;3
lda col,x
ora #4
sta area+3,y
sta area+10,y
;4
lda col,x
ora #6
sta area+4,y
sta area+9,y
;5
lda col,x
ora #8
sta area+5,y
sta area+8,y
;6
lda col,x
ora #10
sta area+6,y
sta area+7,y
;last
lda #0
sta area+13,y
rts
.endl
;---------------------
.local clear_area
ldx #15
@ lda posi,x
sta pos,x
lda #1
sta ri,x
dex
bpl @-
inx
txa ;0
@ sta area,x
dex
bne @-
rts
;----------
posi .he 00 0c 18 24 30 3c 48 54 60 6c 78 84 90 9c a8 b4
.endl
;---------------------
.local chg_shape
jsr clear_area
inc shape
lda shape
cmp #4
beq sixteenth
cmp #3
beq eighth
cmp #2
beq quarter
cmp #1
beq half
;all ;was set during clear_area
rts
half
ldx #7
lda #0
@ sta ri+8,x
dex
bpl @-
rts
quarter
ldx #4
lda #0
@ sta ri+4,x
sta ri+12,x
dex
bpl @-
rts
eighth
ldx #1
lda #0
@ sta ri+2,x
sta ri+6,x
sta ri+10,x
sta ri+14,x
dex
bpl @-
rts
sixteenth
ldx #15
lda #0
@ sta ri+1,x
dex
dex
bpl @-
stx shape ;reset shape color value to initial $ff
rts
.endl
;---------------------
area ;area of stripes
; .ds 210 ;not needed on disc boot
;---------------------
.endp
;---------------------------
fin
.if <fin < 128
;---
.rept 128-<fin ;Sektor noch auffüllen
.he 00
.endr
;----
.else
;----
.rept 256-<fin
.he 00
.endr
;----
.endif
;---------------------------
.rept 359-sectors ;SD disc will be our goal
:128 .he 00
.endr
;---------------------------
;sector 360 := VTOC
;---------------------------
.he 02 ;DOS 2 DIR
; .he d0 02 ;720 Sectors disc
.he c5 02
.he 00 00 ;0 free sectors
.he 00 00 00 00 00 ;unused space in VTOC
;10-99 -> mark all as used
:90 .he 00
;100-127 -> unused
:28 .he 00
;---------------------------
;Sector 361-368 := DIR
;---------------------------
.he 22 ;file locked + inuse
.he 00 00 ;file size in sectors
.he 00 00 ;start sector number
dta '-----------'
.he 22 ;file locked + inuse
.wo sectors ;file size in sectors
.he 01 00 ;start sector number
dta '16 bars PPs'
.he 22 ;file locked + inuse
.he 00 00 ;file size in sectors
.he 00 00 ;start sector number
dta '-----------'
.rept 5
:16 .he 00 ;no file
.endr
.rept 7
:128 .he 00
.endr
;---------------------------
.rept 352
:128 .he 00
.endr
Es wird hier eine 720kB "Diskette" direkt mit dem Assembler erzeugt, die das eigene Programm bootet. Es wird auch eine Directory angelegt, die im DOS 2.5 und auch im BiboDos angezeigt wird. Ich habe aber frech die komplette Diskette als belegt markiert und auch nur die Dateilänge des eigenen Programms eingetragen.
Das atr hat aber noch ein paar Probleme - irgendwann untersuche ich das auch mal genauer.
Irgendwo ist es noch nicht komplett kompatibel - zumindest meckern alle Tools am PC. Das atr startet aber problemlos direkt am ATARI (von SD oder auch vom USB-Stick - Diskdrives gehen bei mir momentan beide nicht mehr 😞 ) und im Emulator.
Möchtest Du keine Directory schreiben, nimm Folgendes (ab fin):
fin
;---------------------------
.if <fin < 128
;---
.rept 128-<fin ;Sektor noch auffüllen
.he 00
.endr
;----
.else
;----
.rept 256-<fin
.he 00
.endr
;----
.endif
;---------------------------
; .rept 1040-sectors ;noch weitere 1039 Sektoren (MD)
.rept 720-sectors ;SD
:128 .he 00
.endr
PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo
Vielen Dank für den Code, aber so ganz habe ich es noch nicht verstanden, wie ich den Code in mein Programm einbinde, damit daraus dann eine Bootdiskette erstellt wird. LG Peter
Im Wesentlichen benötigst Du den Code von "compileto. equ $2000 " bis zum Ende von ".proc init". Vor die eigentliche Startroutine Deines Programms kommt das ".proc Start". Dann noch unten ab ".endp" direkt vor "fin" den Rest.
Dein Programm sollte in nach laufender Reihenfolge assembliertes werden, also kein ".org $6000" vor einem ".org $2000" machen. "opt f+" sorgt dafür, dass alles direkt hintereinander assembliert wird ab dem ersten "org".
compileto ist Adresse ab der dann alles im Speicher liegt. Hier kann man dann ohne DOS deutlich runter gehen mit der Startadresse. Nur im Beispielcode geht weniger als $1000 nicht, da ich ja die PMBASE absolut definiert habe und auch nichts lösche...
PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo
... vielen Dank nochmals! Ich habe das jetzt so in meinen Code eingebaut.
compileto equ $1000
mein Programm startet bei $2000 nach .proc init / .endp beginnt mein Programm mit allen icl und dann mit .proc start
ganz am Ende hinter meinem Programm habe ich dann deine fin Routine gesetzt (brauche ich die?).
Wenn ich den Code aus Eclipse starte kommt nur noch Boot Error (das ist wohl normal). Wenn ich diese Datei als r2phobos.xex direkt starte läuft das Programm. Müsste ich jetzt quasi die r2phobos.xex Datei auf eine Diskette spielen und dann läuft das Programm bootfähig am Atari direkt von der 1050?
/*
16 bars boot disc based on 510b+ from nyd2022
*/
; @com.wudsn.ide.asm.hardware=ATARI8BIT
; @com.wudsn.ide.asm.outputfileextension=.atr
compileto equ $1000
sectors equ ((fin-compileto)/128)+1
opt f+ ;Activate fill mode
opt h- ;no headers
;;; ATR disk header
.word $0296, $8, $80
:10 .he 00
org compileto
;--------------------------- boot init
.proc boot
.he 00 ;always 0
dta b(sectors) ;how many sctors to load
.wo boot ;load address
.wo init ;init address (seems not to be used)
jmp start
; mva #$24 710
.endp
;--------------------------- boot init end
.proc init
;you can start an intro here
jmp *
rts
.endp
;---------------------------
;---------------------
org $2000 ;4096
icl '../hardware.txt'
icl 'header.txt'
icl 'character.asm'
icl 'pmg_vars.asm'
icl 'VBI.asm'
icl 'Sfx-Engine.asm'
.proc start
main1 mwa #40960 bilds1
mwa #41000 bilds11
mwa #42460 bilds2
mwa #42500 bilds21
mva #11 wsync
mwa #dlist 560
mva #151 fuelzaehleritem
mva #0 fuelzaehler
mva #10 store1
mva #170 store3
mva #16 sound12
jsr text
Start1
;50Hz oder 60 Hz
mva #0 vcount
@ lda vcount
beq @+
sta grafmod
jmp @-
@ lda grafmod
cmp #155
bmi @+
;PAL
mva #50 grafmod
jmp @+1
@ ;NTSC
mva #9 grafmod
@
jsr variablensetzen
jsr pmvorbereiten
ldy #0
ldx #0
ldx #>vbinter ;VB-Interrupt VektorHi
ldy #<vbinter ;VB-Interrupt VektorLo
lda #7 ;Deferred Mode mit lda #7 festlegen
jsr setvbv ;Vektor für die eigene Routine über setvbv eintragen
lda #5
ldx #2 ; Kanal 1 wählen
sec ; force
jsr xSFX.START
hauptprogramm
.........
........
......
.......
@ lda #32
sta scorez2
sta 42060
sta 43560
inc scorez3
lda scorez3
sta 42059
sta 43559
rts
.end
icl 'lands.asm'
fin
;---------------------------
.if <fin < 128
;---
.rept 128-<fin ;Sektor noch auffüllen
.he 00
.endr
;----
.else
;----
.rept 256-<fin
.he 00
.endr
;----
.endif
;---------------------------
; .rept 1040-sectors ;noch weitere 1039 Sektoren (MD)
.rept 720-sectors ;SD
:128 .he 00
.endr
;run start
Alle ORGs im Programm müssen raus. Mit ".ALIGN $1000" kannst Du nachfolgenden Code an den nächsten 1000er binden. ".ALIGN $0400" hilft bei Fonts.
Der letzte Teil schreibt die fehlenden Bytes der "Diskette" also muss das zwingend da sein.
PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo
mein Programm hat ja nur ein org .. also das muss raus! Was ist mit org compileto? Das muss drin bleiben?!
Prodehl schrieb: mein Programm hat ja nur ein org .. also das muss raus! Was ist mit org compileto? Das muss drin bleiben?!
Ja, das eine org muss bleiben. Der Atari muss ja wissen wohin er laden soll.
PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo
ok... und dann daraus eine atr erstellen und dann auf eine leere formatierte Diskette speichern?!
Wo steht mein Projekt? Alle Sonderitems sind fertig - die Charaktertabelle ist auch voll! Die Landschaft habe ich weiter ausgebaut, ich denke in den nächsten 1-2 Wochen ist sie auch komplett fertig. Das automatische Scroll hört ja irgendwann auf und dann muss man aktiv selber runterscrollen - das ist auch nötig, da die Hindernisse sonst nicht passierbar sind (im Beispiel unten habe ich es für den Zweck der Landschaftserstellung rausgenommen, normalerweise fährt man mit dem Schiff ganz langsam und vorsichtig durch die Hindernisse). Und genau hier habe ich in den letzten Tagen rumgefeilt. Die Feinscroll-/Grobscrollroutine musste ich extra dafür anpassen, denn man muss ja jeden einzelnen (von den 8) Feinsteps fahren können, nicht - wie vorher - einen kompletten Feinscrolldurchlauf. Das habe ich heute programmiert und jetzt fliegt das Raumschiff sehr flüssig und sehr filigran Step für Step (wenn man es so steuert) weiter. Da musste ich noch etwas Code und Gehirn reinstecken. An die Explosionen muss ich nochmal ran, denn die schöne Lösung der mitlaufenden Explosionen beim automatischen Scroll sind hinderlich, denn wenn das Raumschiff steht und man ballert einen Tank ab, dann kommt automatisch der Scroll rein für die 4 Explosionsphasen... Wenn ich das gefixt habe, kommt der Part mit der Schiffskollision. Das erkennt er schon, aber ich muss die Aktion noch programmieren: Explosion des Schiffes, Verlust eines Schiffes, zurück zu einem vorherigen Punkt gehen, Sound dafür. Dann kommt noch das Auffüllen eines Schiffes bei einem bestimmten Score. Danach gehe ich nochmal ganz intensiv an die Kollisionserkennung. Die ist gerade bei Nahdistanz noch zu fehlerhaft... das will ich perfekt hinbekommen. Wenn das alles fertig ist, kommt der Endgegner - hier bin ich noch völlig blank... irgendetwas cooles muss her. Dann das Intro incl. Sound - der Introsound soll dann während des Spieles leise weiterlaufen... Wie man sieht: Da ist noch viel zu tun!! Ich stelle das Spiel auf jeden Fall fertig und es soll schön spielbar sein! Mein erstes komplettes und komplexes Projekt für Atari!. Ob ich es dann später für den Abbuc-Wettbewerb einreiche... fraglich. Vielleicht hat es zu viele Ähnlichkeiten mit Phobos von damals... vielleicht baue ich die ganzen Grafiken und Charakter später noch um und baue daraus etwas anders... mal sehen!
Und hier noch ein kurzes Video von dem neu erstellten Landschaftspart - wie gesagt, später fährt man hier langsam selbstgesteuert durch:
Liebe Grüße Peter
Hi! Solange es Deine eigene Kreation ist und Du keine Urheberrechte verletzt, solltest Du damit am Software-Wettbewerb teilnehmen können. Du darfst es nur nicht vorher veröffentlichen... Das ist ja der Punkt, wo ich auch unsicher bin. Sonst hätte ich von meinem Projekt auch mal etwas gepostet 😉
Grüße Janko
Meine Projekte findest Du hier...
Ich stelle ja hier nur Fragmente des Programmes rein und ab und zu mal einen kleinen Ausschnitt als Video. Das Programm so ist ja noch nicht fertig und schon gar nicht spielbar.
Sollte das dennoch ein Problem machen, dann ist es halt Pech 😉
Wenn alles fertig ist, möchte ich nach dem Wettbewerb alle Source-Codes noch massiv mit Bemerkungen und Erklärungen versehen und dann veröffentlichen. Da sind so viele Erkenntnisse mittlerweile - und Fallstricke... klar, die Allermeisten sind schon echte Profis und brauchen das sicher nicht, aber etwaige Neueinsteiger was Assemblerprogrammierung angeht, könnte es helfen. Ich gehe da mal von mir selber aus: Mir hätte das enorm geholfen!!!
Ich hatte so viele Probleme zu bewältigen (und da gibt es noch ein paar) - alleine die weiterscrollende Explosion war so tricky... Kollege Christensen hatte damals ja auch so seine Probleme damit und es auch erst bei Phobos richtig gelöst... in Caverns of Mars 1 war das noch nicht der Fall wie man gut auf youtube sehen kann! Caverns of Mars 2 war schon etwas komplexer und bei Phobos hat er alles perfekt programmiert! Schade, daß er danach völlig abgetaucht ist!
Prodehl schrieb: ok... und dann daraus eine atr erstellen und dann auf eine leere formatierte Diskette speichern?!
Mit dem Code entsteht direkt eine atr Datei.
PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo
Was gibt es Neues? RTP hat eine weitere Facette vor der ich echt richtig Bammel hatte. Das Spiel hat jetzt ein richtig schönes 3-stimmiges Intro mit laufender Hintergrundmusik. Da muss ich jetzt großen Dank an Janko loswerden, der die alte Vorlage aus der Hexenküche (damit sind auch meine ersten Töne entstanden) stark erweitert hat und so eine wirklich schöne aber dennoch schlanke Engine gemacht hat. Diese läßt sich leicht in den asm - Code einbinden! Dann habe ich von ihm noch den Tipp bekommen mir auf fiverr.com für schmales Geld eine 8-bit Retromusik komponieren zu lassen, über eine Partitur kann man dann die Töne und den Takt auslesen und ins System reinbringen... Janko (so viel verrate ich schon mal) schreibt gerade an einen Midi-Analyse-Konverter... damit kann jeder ohne Kenntnisse die Sounds in den Atari einbringen... einfach fantastisch und es funktioniert scho!!! Ich hoffe, daß er dieses Projekt noch verfeinert... nochmals vielen vielen Dank, Janko!! Musik ist drin, nun gehts weiter mit dem Code.... und ich habe noch satte 11kb frei! LG Peter2
.... die dreistimmige Musik überlastet jetzt leider den VBI bei 60 Hz. Sauber spielen kann man es jetzt nur im 50 Hz-Modus. Ich mache jetzt erstmal die Landschaft komplett fertig und programmiere das Endlevel und die vielen Kleinigkeiten, die noch notwendig sind. Dann kümmere ich mich um die Kollisionsabfrage (da gibt es noch ein paar Fehler) und dann kommt das Intro. Ich überlege auch, ob ich die Grafik etwas umbaue, damit das Spiel nicht zu nah am Original Phobos ist. Wenn alles fertig ist, kümmere ich mich noch ganz intensiv an der Optimierung des VBI, damit die Hintergrundmusik auch im 60 Hz Modus spielt und das Spiel funktioniert. Falls das nicht klappt, ändere ich die Hintergrundmusik in 2 - oder 1 -stimmig .... aber jetzt erstmal die Landschaft, am liebsten soll die bis zur NOMAM fertig sein!
Hi,
Prodehl schrieb: das Teilen durch 8 geht mit drei ROR-Anweisungen!
vielleicht ist es schon aufgefallen, aber falls nicht: wenn man ROR benutzt, kommen die Bits, die man rechts rausschiebt, über und mit Carry wieder links rein:
CLC
$1F = %00011111
ROR -> %00001111 1
ROR -> %10000111 1
ROR -> %11000011 1 -> $C3
Meines Erachtens wäre also LSR richtig.
CU, Erhard
Jede Info, die zu Hause auf meinem Rechner liegt habe ich unterwegs nicht verfügbar. Jede Info, die im Netz liegt finde ich nicht wieder, wenn ich sie benötige.
Hallo Erhard, der Post war ja im November und sicherlich noch mit weniger Assembler-Erfahrung meinerseits. Darum habe ich ja auch vor jedem ROR ein CLC gesetzt, die andere Lösung mit LSR ist natürlich besser! An die Kollisionskorrektur muss ich eh nochmal ran, daher habe ich den Code bislang so belassen. Danke aber für den Tip Gruß Peter
Was gibt es Neues bei RTP?
Das Intro ist fertig! Mir bleiben für den gesamten Rest jetzt noch 3100 bytes.... Die Landschaft ist fertig, der Sound für die Schüsse und Explosionen sind drin, funktionieren aber noch nicht so richtig gut bzw. nicht mehr... die Kollision für das Raumschiff muss noch rein. Da wird noch etwas Code benötigt und wohl den ganzen Rest verschlingen. Danach kommt die ganze Fehlerbereinigung. Ich habe noch etwas überflüssigen Code drin, den werde ich noch rausschmeissen und so noch etwas Platz schaffen... viel geht aber nicht mehr. Das bedeutet aber, das das Programm auch bald dann fertig ist. Ich denke am meisten Zeit werde ich noch brauchen, um die Fehler zu beseitigen und um Code zu optimieren.... Gruß Peter
Hi,
da ist ein Grafikfehler nach dem Textscroller bei ca. Sekunde 19 ...
Schöne Ostern
Erhard
Jede Info, die zu Hause auf meinem Rechner liegt habe ich unterwegs nicht verfügbar. Jede Info, die im Netz liegt finde ich nicht wieder, wenn ich sie benötige.
Guten Morgen Erhard, vielen Dank für die Info! Der Fehler tritt auf, wenn man auf Start drückt und das Programm vom Intro (Textscroller) auf Game umschaltet. Ich nutze für das Intro eine andere Displaylist und einen anderen Charakterset... den Fehler kenne ich, habe ihn aber noch nicht lokalisiert... mir fällt gerade was ein, das probiere ich gleich mal aus! Danke für die Inspiration!! Schöne Ostern Gruß Peter
....der Bildschirm ist noch nicht leer - beim Umschalten auf den anderen Charakterset wird die Schrift dann entsprechend kryptisch... Ich muss den gesamten Bildschirm löschen beim Umschalten vom Intro zum Hauptprogramm! Jetzt hab ich es (war eigentlich fast klar) ... Danke Erhard!
Fehler gefixt!!
Moin moin, da habe ich mal wieder ein dumme Frage in die Runde: Mein Intro ist fertig... mit Musik und Textscroll... das läuft so munter vor sich hin bis ich Start drücke und dann geht das Spiel los... so die Theorie. Allerdings muss ich manchmal mehrmals auf Start drücken, bis er es erkennt, da das Introprogramm gerade woanders ist. Das ist natürlich blöd, denn wenn man Start drückt, soll es auch gleich losgehen. Ich dachte - schlau wie ich bin - das könne ich im VBI lösen. Denkste. Die 2. Hälfte des VBI schreibt immer #8 in die Consol.... das muss doch besser gehen??? Wo ist hier der Haken? Gruß Peter
Hallo Peter!
Ich frag mich gerade wie umfangreich Dein Intro ist, da bei mir das ganze wie folgt aussieht:
lda #$08
sta CONSOL
jsr TitleVBI.An ; Titel-MUSIK einschalten
Loop lda #$00 ; Farbwechsel verhindern
sta ATRACT
lda CH ; Prüfen ob ESC gedrückt wurde
cmp #$1c
beq Exit
lda CONSOL ; Prüfen ob START gedrück wurde
cmp #$06
bne Loop
Exit jsr TitleVBI.Aus ; Titel-MUSIK abschalten
Im "TitleVBI" wird die Musik und jegliche Ausgabe gesteuert, so dass die Hauptschleife lediglich die Start- und Esc-Taste ausliest.
Grüße Janko
Meine Projekte findest Du hier...
hmmm ... klar, bei mir läuft alles in der Hauptschleife: Musik, Grob- und Feinscrolling..... Dann baue ich das um und lege das alles in einen VBI und mache die Schleife ganz schlank! Danke für die Eingebung, Janko!!
Hallo!
Ich denke nicht, dass es zwingend im VBI liegen muss, es sollte nur möglichst schnell abgearbeitet werden können.
Janko
Meine Projekte findest Du hier...
ok, aber du hast ja auch ein schönes Scrolling im Intro - das läuft doch sicherlich dann im VBI?!
Prodehl schrieb: Moin moin, da habe ich mal wieder ein dumme Frage in die Runde: Mein Intro ist fertig... mit Musik und Textscroll... das läuft so munter vor sich hin bis ich Start drücke und dann geht das Spiel los... so die Theorie. Allerdings muss ich manchmal mehrmals auf Start drücken, bis er es erkennt, da das Introprogramm gerade woanders ist. Das ist natürlich blöd, denn wenn man Start drückt, soll es auch gleich losgehen. Ich dachte - schlau wie ich bin - das könne ich im VBI lösen. Denkste. Die 2. Hälfte des VBI schreibt immer #8 in die Consol.... das muss doch besser gehen??? Wo ist hier der Haken? Gruß Peter
Frage doch einfach die Tasten im VBI oder DLI ab und starte dann von dort aus das Spiel.
PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo
Ich wollte ja die Start-Taste mit CONSOL im VBI abfragen, der VBI schreibt aber in der 2. Hälfte da immer den Wert 8 rein... DLI wäre noch eine gute Idee...
Prodehl schrieb: ok, aber du hast ja auch ein schönes Scrolling im Intro - das läuft doch sicherlich dann im VBI?!
Ja, bei mir läuft alles im VBI, Musik und die beiden Scroller. Die Farbe wird im DLI geändert.
Janko
Meine Projekte findest Du hier...
Frag Start doch einfach im VBI ab und wenn es gedrückt wurde, setz ein Flag. Dieses Flag prüfst du an einer Stelle, die zum Start des Spiels passend ist. Wenn es gesetzt ist, löschst du es wieder und startest das Spiel. Das ist quasi die Umkehr dessen, wie die Schattenregister in Page $2xx verwendet werden.
das mit dem Flag setzen habe ich schon versucht… das funktionierte nicht besser… das schaue ich mir nochmal in Ruhe an! Den korrekten DLI Aufruf nach Buch führte bislang zum Absturz… keine Ahnung was ich da falsch mache… ich muss mich nochmal intensiv mit dem DLI beschäftigen! @Janko: Beim Grobscroll im VBI muss du doch ne Menge Daten rumschieben… wird das nicht zeitkritisch??
Das "Grobscrolling" erreiche ich durch Displaylistmanipulation, indem ich die Speicheradressen in der Displaylist verschiebe. Das ist dann Ruck-Zuck erledigt.
Hier der Beispiel-Code... aber die Variablenamen bitte ignorieren 😳
@ ; ######## Vertikales Grobscrolling durch Displaylist-Manipulation
lda #$00 ; Feinscrolling auf 0 setzen
sta VSCROL
lda TitelSC2+1 ; Die Zeile die oben verschwindet
sta TextNeu1+1 ; und unten mit neuen Text erscheint
sta TextNeu2+1 ; muss zwischen gespeichert werden
lda TitelSC2+2 ; Hier noch das Hi-Byte
sta TextNeu1+2
sta TextNeu2+2
ldx #$00 ; Nun alle Zeilen umkopieren
@ lda TitelSC2+4,x ; aber nur die Angabe der
sta TitelSC2+1,x ; Speicheradresse
lda TitelSC2+5,x
sta TitelSC2+2,x
inx ; 3 Schritte weiter
inx
inx
cpx TitelScrollLast ; Alle Zeilen abgearbeitet?
bcc @-
lda TextNeu1+1 ; Nun die gemerkte 1. Zeile
sta TitelSC2+1,x ; unten noch anfügen
lda TextNeu1+2
sta TitelSC2+2,x
Die Displaylist sieht bei mir dazu so aus:
TitelDLst .byte $70,$70,$F0 ; 24 leere Scanzeilen (der normale obere Block)
.byte $4D,<TitelGfk,>TitelGfk ; Grafik 13 (Gr. 7) und Speicherzuweisung
.byte $0D,$0D,$0D,$0D,$0D,$0D ; weitere 25 Zeilen Gr. 7
.byte $0D,$0D,$0D,$0D,$0D,$0D ;
.byte $0D,$0D
.byte $70,$70,$F0 ; noch weitere leere Scanzeilen
TitelSC2 .byte $62,<SPScrMem01,>SPScrMem01 ; Ab hier Text Gr. 0 mit vertikales
.byte $62,<SPScrMem02,>SPScrMem02 ; Scrollen
.byte $62,<SPScrMem03,>SPScrMem03 ;
.byte $62,<SPScrMem04,>SPScrMem04 ;
.byte $62,<SPScrMem05,>SPScrMem05 ;
.byte $62,<SPScrMem06,>SPScrMem06 ;
.byte $62,<SPScrMem07,>SPScrMem07 ;
.byte $62,<SPScrMem08,>SPScrMem08 ;
.byte $62,<SPScrMem09,>SPScrMem09 ;
.byte $62,<SPScrMem10,>SPScrMem10 ;
.byte $E2,<SPScrMem11,>SPScrMem11 ;
.byte $62,<SPScrMem12,>SPScrMem12 ;
.byte $42,<SPScrMem13,>SPScrMem13 ;
.byte $70,$70,$F0 ; wieder leere Zeilen
TitelSC1 .byte $56,<TitelScrl,>TitelScrl ; Gr. 1 mit horizontales Scrolling
.byte $41,<TitelDLst,>TitelDLst ; JVB, und die Displaylist wieder starten
Meine Projekte findest Du hier...
... ich habe jetzt im Immediate-VBI eine kleine Routine drin, die CONSOL abfragt und falls gedrückt ist einen Werte in eine Variable einschreibt, die ich dann später in der Introschleife auslese und entsprechend das Hauptprogramm startet (so wie von DjayBee vorgeschlagen). Da hatte ich wohl vorher einen kleinen Fehler drin... Jedenfalls funktioniert es jetzt bestens! Danke für die Kommentare und Ideen...es ist wirklich super hier im Forum. Jeder hilft jedem. Und es macht echt Spass, sich hier so auszutauschen. @Janko: Dieses Scrolling mit der DL werde ich beim nächsten Projekt umsetzen, das erscheint mir viel besser. Danke dafür! Vielleicht nehme ich dann auch eine Bitmap-Grafik... mal sehen! Gruß Peter
Peter, Scrolling im VBI macht es zunächst einfacher immer "im Takt des Systems" zu bleiben. Allerdings muss man halt an die Zeit denken, die gerade bei NTSC Systemen deutlich knapper ist. Für den Sound sollte man am besten immer testen, ob man einen Atari mit 50 oder 60 Hz hat und die Abspielgeschwindigkeit anpassen. Bei manchen Spielen ist das sogar auch für das gesamte Spiel sinnvoll. Auf NTSC sind manche Dinge dann halt schneller, wenn man es nicht anpasst.
Grüße aus Bärlin, Ralf
PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo
Hallo Ralf, vor meinem nächsten Projekt werde ich mir auf jeden Fall Gedanken machen, wo ich wie was mache. Bei RTP habe ich ja relativ wild losprogrammiert und bin dann immer tiefer in die Materie eingetaucht. Bislang konnte ich alle größeren Probleme lösen - weiß aber genau, daß vieles anders vielleicht besser hätte gehen können. So hat mich z.B. das ganze Zeittiming echt immer wieder beschäftigt und oftmals durch notwendige Programmänderungen unerklärliche Ruckler beim Scrolling beschert. So musste ich z.B. die Idee von 4 Schüssen aufgeben, weil ich es einfach nicht mehr sauber hinbekommen habe, ohne das es woanders hakte. Die Ruckler habe ich jetzt mittlerweile ganz gut im Griff durch richtiges Timing von RTCLOK - das Feinscrolling z.B. läuft bei mir im Hauptprogramm und wird durch RTCLOK gesteuert. Die eigentlichen unerklärlichen Ruckler bekomme ich mit der Abfrage PAL oder NTSC in Kombination mit vcount und entsprechenden kleineren Pausen auf vcount getriggert in den Griff. Damit würde ich auch die 4 Schüsse hinbekommen... aber das jetzt alles umzubauen macht keinen Sinn, das setze ich den im nächsten Part um. Auch das ganze Scrolling werde ich anders machen - nämlich mit DL Verschiebungen... vielleicht baue ich dann dann das Spiel in einer Bitmapgrafik auf. Was ich wirklich gelernt habe in den letzten ca. 6 Monaten ist die erstaunliche Komplexität dieses kleinen Rechners. Es gibt so viele Möglichkeiten und aber auch Beschränkungen wo man wirklich gut planen muss... Thema Speicher, Geschwindigkeit, Charakter etc etc.... Liebe Grüße Peter
p.s. Ich habe heute die allererste Betatestversion fertig - das Programm läuft komplett vom Intro zum Spiel - mit Sounds, Musik, Explosionen, Score, Schiffe (man hat 5) werden zerstört, Ende und Rücksprung zum Intro mit möglichem Neustart. Es fehlt noch das Endlevel und etliche Bugs müssen noch fixiert werden, auch ist die Landschaft noch in Teilen zu schwer... das muss noch spielbarer werden! Auf jeden Fall wird am Ende ein komplettes und fertiges Spiel entstanden sein für alle, die Bock drauf haben.... 😉
Status Return To Phobos:
Das Spiel ist im Prinzip fertig!
Ich habe im Grunde alle Elemente jetzt drin und man kann das Spiel vom Anfang bis zum Ende komplett durchspielen. Dabei gibt es ein Intro und ein Extro, einen durchgehend scrollenden Part, einen Part wo man aktiv nach unten sich scrollend bewegen muss. Es gibt eingeschobene Zwischenlevel und einen Endgegner, den man besiegen muss. Alle Sounds sind drin incl. der Musik (es gibt drei verschiedene Musikstücke). Die Items habe ich umgearbeitet und das Spiel heisst jetzt auch anders - somit sind auch mögliche alte Rechte gewahrt.
Was ist noch zu tun? Die Landschaft gehe ich jetzt intensiv durch nach guter Spielbarkeit (ein paar Ecken erscheinen zu schwer), es gibt noch ein paar kleine Bugs, die ich bearbeiten muss. Die Kollisionserkennung mit Explosion der Items ist noch zu ungenau - hier werde ich noch Hirnschmalz reinstecken. Dann wird getestet (Janko) und meine Frau kümmert sich noch um den englischen Text (mein Englisch ist naiv).
Freier Speicher für Coding: Noch ca. 1300 Bytes... das reicht noch für Kleinigkeiten, aber ich bin ja auch fertig. Ein aufwendiger Highscore ist da wohl nicht mehr drin... und dann gehts zum Holger 😉
Grüße Peter
Status des Spiels: Return To Phobos heißt jetzt Battle Of Eris ! Eris ist ein kleiner Zwergplanet am Rande des Sonnensystems und wurde erst vor ein paar Jahren entdeckt. Meine Geschichte setzt hier an, denn die Aliens sind nach der verlorenen Schlacht auf Phobos nach Eris geflohen und jetzt wieder erstarkt.
Das Spiel ist jetzt fertig. Ich habe noch einen Highscore eingebaut mit insgesamt drei Rankingplätzen, die auch auf Diskette abgespeichert werden. Der Speicher ist jetzt wirklich ausgereizt... mir bleiben noch genau 170 Bytes...
Es gibt 3 verschiedene Musikstücke fürs Intro und Extro, für das Spiel selber und für die Zwischenlevel. Man spielt in mehreren Phasen: 1. Der Autoscrol 2. Der Scrol durch aktiven Joystickeinsatz mit anderen Items 3. Der Endgegner Die Zwischenlevel kommen im Autoscrol.
Das Spiel läßt sich nur mit einem Atari 130 XE spielen. Im PAL-Modus läuft es schön flüssig, NTSC ruckelt leider... das werde ich auch nicht viel besser hinbekommen, da der VBI und die CPU vom Timing komplett ausgelastet sind. Die gesamte Entwicklung des Spiels hat jetzt fast ein Jahr gedauert... ich kann mich noch gut an meine ersten Schritte erinnern, wo ich überlegt habe, wie ich "Hallo Welt" scrollend auf den Bildschirm bringe... Ich hatte große Hilfe von JAC und Sascha auf der Fujiama letztes Jahr mit der Einrichtung meiner Programmierumgebung, danke an alle, die mir hier im Forum immer wieder wichtige Inputs gegeben haben! Mein besonderer Dank gilt natürlich meinem neuen Freund Janko, ohne dessen Beistand in etlichen Fragen wäre das Programm nie so geworden ... danke Janko!!
Ob das Spiel würdig genug für den Wettbewerb ist oder nicht, ist mir gar nicht so wichtig... aber wenn es ein einziger gerne mal spielt und ein wenig Gefallen dran findet, dann bin ich mehr als zufrieden! Gruß Peter
Hallo Peter,
irgendwie habe ich Probleme mit dem Spiel. Sehr häufig passiert nichts mit den Objekten wenn ich auf sie schieße. Oder eine Explosion findet irgendwo im normalen Playfield statt wo sich gar kein Objekt befindet. Meine Hardwareconfig: 800XL mit Turbo Freezer / FujiNet
Du hast geschrieben das es nur auf 130XE läuft. Deshalb habe ich es mal im Altirra mit 130 XE Config (OS Rev. 3) probiert: Aber da läuft es auch nicht richtig. Ist ggf. die Version für den Softwarewettbewerb (MAG150H.ATR) defekt?
Schau mal das Video: https://drive.google.com/file/d/1cwzp2OJouqCVg6jLU7cIaA8t--UQ312c/view?usp=sharing
Wenn das Spiel frisch gebootet ist, funktioniert das allererste Mal spielen am besten. Da gehen noch die meisten Objekte kaputt. Aber wenn man dann gestorben ist wird es schon recht schnell "komisch" und reagiert eben nicht mehr richtig.
Altirra Config: Base system PAL 130XE Additional Devices None OS Firmware Atari XL/XE OS ver.3 [29F133F7] Mounted Images Disk: MAG150H.ATR
Hallo, vielen Dank für die Rückmeldung! Ich habe gerade die final Version am Mac-Emulator und am Altirra getestet - alles läuft wunderbar! Allerdings - und das ist mir schon auf der Fuji aufgefallen als ich andere beim spielen von BoE beobachtet habe - läuft die Schuss-/Kollisionserkennung nicht bei Dauerfeuer. Das habe ich einfach nicht bedacht und entsprechend abgefangen, da mein Joystick diese Funktion nicht besitzt. Janko und ich haben das Spiel wochenlang getestet und konnten die allermeisten Bugs finden und entfernen - nicht alle allerdings. Manchmal kann man durch die Landschaft schiessen und hin und wieder erkennt er die Kollision nicht, wenn man ein Objekt trifft - es liegt wohl am timing und könnte mit dem Dauerschuss in Zusammenhang stehen. Die Schüsse sind ja gewollt so, daß man immer nur einen Schuss abgeben kann und zwar wechselweise links / rechts. Ich denke wenn man Dauerfeuer drückt, verliert das Programm den Kollisionsstatus... in CavernsOfEris wird es das nicht so geben. Also: Kein Dauerfeuer bitte!! 😉
... übrigens... das Spiel ist nicht leicht, aber mit ein wenig Übung kommt man bis zum Endgegner und kann diesen auch besiegen! Ich persönlich bin mehrfach komplett durchgekommen, schaffe es aber auch nicht immer. Am absolut schwierigsten sind die breiten Energiebarrieren, da muss man echt ganz genau das timing hinbekommen. Auch durch das Energielabyrinth muss man erstmal durchkommen - wobei, wenn man den richtigen Weg kennt, ist es gar nicht so schwer 😉
Ja, es ist definitiv nicht einfach. Manchmal komme ich nicht mal um die ersten Ecken, oder lande in der Mauer. Versterbe IN der Mauer, also nicht an der Mauer 😁 . Ohne Dauerfeuer. Gespielt am MacBookPro/Intel mit Atari 800 MacX Gruß Wolfgang
... ich habe gerade mal ein kurzes Spielchen gemacht und es gerade auf youtube hochgeladen... bin jetzt leider auch nicht ganz durchgekommen auf Anhieb, aber recht weit gekommen... Hier der Link:
Tatsächlich! Wenn man nur Einzelschüsse absetzt ohne den Feuerknopf gedrückt zu halten geht es viel besser. ok!